Tips for writing Dockerfiles

Sebastian Otaegui

 4 min read

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:

loading

GOOD:

loading

Note 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:

loading

GOOD:

loading

When using VOLUME, specify all the volumes in the same line as an array. For example:

BAD:

loading

GOOD:

loading

A couple of extra tips

When using ENV you can specify multiple environment variables in a single line resulting in a single layer. For example:

loading

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:

loading

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