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.
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
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:
RUN echo "\ndeb http://nginx.org/packages/debian/ jessie nginx" >> /etc/apt/sources.list RUN wget http://nginx.org/packages/keys/nginx_signing.key -O - | apt-key add - && \ RUN apt-get update -y RUN apt-get install -y --no-install-recommends nginx RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf RUN rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin
RUN echo "\ndeb http://nginx.org/packages/debian/ wheezy nginx" >> /etc/apt/sources.list && \ wget http://nginx.org/packages/keys/nginx_signing.key -O - | apt-key add - && \ apt-get update -y && \ DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends nginx && \ echo "\ndaemon off;" >> /etc/nginx/nginx.conf && \ rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin
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.
EXPOSE, you can specify as many ports as you want in a single line. For example:
EXPOSE 2181 EXPOSE 2888 EXPOSE 3888
EXPOSE 2181 2888 3888
VOLUME, specify all the volumes in the same line as an array. For example:
VOLUME /tmp/dir1 VOLUME /tmp/dir2
VOLUME ["/tmp/dir1", "/tmp/dir2"]
A couple of extra tips
ENV you can specify multiple environment variables in a single line resulting in a single layer. For example:
ENV TMPDIR="/tmp" APPDIR="/app"
The use of
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:
FROM busybox VOLUME ["/newdir", "/app"] WORKDIR /APP1
will create a docker image that has 3 new directories
/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
Sebastian Otaegui is a system admin currently living in Buenos Aires. He started his career working as one of the web hosting administrators in the eBusiness hosting team at IBM, soon he got tired of the red tape that big organizations suffer. After working for one year for a very large extended warranty company, he was asked to move to Chicago to work as the team leader for the web hosting administration team. During the six years working at The Warranty Group he met Cedric. Sebastian and Cedric became friends and begun introducing concepts that back then didn't have a name and today are known as DevOps practices.
In his free time, Sebastian enjoys trying new technologies, watching movies with his wife and playing Star Wars The Old Republic. Fun fact about Sebastian is he played rugby for 14 years.