Tiny PHP Docker images

Docker has been around for a while now and I had my go at a few systems.
With some trial and error I worked up an intermediate knowledge of the inner workings of docker and how it feels to develop with it, from a developer and a devops perspective.

The DevOp in me wants to try out all the new tool, frameworks, scripts to automate as much as possible for my development, however the developer in me is very unhappy having to wait for hundreds of Megabytes (on larger projects it is in the GB range) of images to load and in the worst case I waited an hour for an image build to finish.

Hence I had to do something. I had to find a way to make those images smaller.
On one project we are using eZ Platform, which comes with a docker toolbox.

While developing with it, I don’t notice much, however when I send my project to be built on the CI server, I will always have to pull the base images provided which are quite large:

ezsystems/php 7.0-v1-dev 522.9 MB
ezsystems/php 7.0-v1 451.1 MB

This is a little bit of an overhead, so I searched in my scripts collection and put something together that will build me a stand alone php package, and called it packager which makes use of dockerize.

I can feed packager with a json file which describes which apt packages I want installed, which essential binaries I want and which applications I want to have packaged. Packager then uses an ubuntu:xenial image to execute those instructions, put all the files together and tars it out into the unix pipe.

Contents of package.json

{
"pre-commands": [],
"post-commands": [
"php -r \"copy('https://getcomposer.org/installer', 'composer-setup.php');\"",
"php composer-setup.php --install-dir=/tmp/build/usr/bin/ --filename=composer",
"php -r \"unlink('composer-setup.php');\""
],
"essentials": [
"env",
"bash",
"sh",
"dash"
],
"packages": [
"libcurl3",
"libedit-dev",
"libgd-dev",
"libmemcached-dev",
"libldb-dev",
"libxpm-dev",
"libxslt1-dev",
"libicu-dev",
"php",
"php-curl",
"php-fpm",
"php-gd",
"php-intl",
"php-memcached",
"php-mbstring",
"php-mysql",
"php-mysqlnd",
"php-pear",
"php-xml"
],
"bin": ["php", "php-fpm7.0"]
}
cat php.json \
| docker run \
--rm \
--name pckgr \
-ia stdin \
-a stdout \
-a stderr packager \
> build.tar

Then I define a Dockerfile for my image:

FROM busybox
ADD build.tar /

ENTRYPOINT ["php-fpm7.0", "-F"]

docker build -t local/php .

After I switched the PHP images the eZ application image was now only about 82MB small. The CI Server only needs to build the base image (which takes about 2 – 5 minutes to build) once a week and the application builds have cut down in time by about 6 minutes.
I have tried this with PHP and NGINX but failed to get erlang to run with it. Maybe some systems are not supposed to be run in isolation.
Check out my repository and feel free to contribute.