Tips for writing Dockerfiles
We've been using docker on our projects recently to ease development and deployment processes. Here are a few tips based on what we learned building and maintaining docker infrastructure for production.
Docker image layers
In the early days of docker, there used to exist a pretty low number limit of layers: it was equal to the Ultimate Question of Life, the Universe, and Everything or if you prefer, the limit of aufs layers (42). That docker limitation has now been overcome, and the layer limit has been increased to 127.
Although the limitation has been increased, it is still a good practice to avoid creating excessive amounts of layers.
Writing Dockerfiles
Each instruction or step that is executed during a docker build
run, creates a new layer and we want to minimize the amount of layers where it makes sense.
Using instructions with multiple operations
When using RUN
try to concatenate several commands together making them make sense as a unit, that is, if you are installing Nginx, use the layer to install Nginx only and remove all the temporary files, to minimize space used by the layer. For example:
BAD:
loadingGOOD:
loadingNote that we remove all the temporary files before ending the command line for the RUN
instruction because once a layer is committed, it keeps the content forever. If the content is removed in the next step/instruction the resulting image will not free up the space.
When using EXPOSE
, you can specify as many ports as you want in a single line. For example:
BAD:
loadingGOOD:
loadingWhen using VOLUME
, specify all the volumes in the same line as an array. For example:
BAD:
loadingGOOD:
loadingA couple of extra tips
When using ENV
you can specify multiple environment variables in a single line resulting in a single layer. For example:
The use of VOLUME
or WORKDIR
will result in the creation of a directory, not only as a mount point reference in the case of VOLUME
, but also as a physical directory in the filesystem of the image. That is:
will create a docker image that has 3 new directories /newdir
, /app
and /APP1
of which two of them can be mounted with docker run -v ~/:/newdir imagename
or docker run -v ~/:/app imagename
and a third directory that is set as the CWD (current working directory) of the runtime.
We hope that you can take these practices and incorporate them into your own code to slim down your Dockerfiles. Got any other suggestions? Tweet them to us: @spantreellc