Docker best practices

The official Docker documentation has a great article covering a wide variety of Dockerfile best practices: https://docs.docker.com/articles/dockerfile_best-practices/. This document highlights some of those items while also pointing out some Vokal specific practices.

Use a .dockerignore file

You can easily exclude unnecessary files and directories from a Docker image you are building by using a .dockerignore file. An example in the linked documentation points out excluding the hidden .git directory from your image. This is a good way to cut down the size of the resulting image. In addition, you can also safely exclude other configuration files that are not needed to run the main app process.

Sample .dockerignore:

.drone.yml
.git
.gitignore
Dockerfile
README.md
docker-compose.yml

Don't install unnecessary packages

Only install the packages that your app needs. Always double-check your Dockerfile if you make a change and stop using a dependency. Also, be vigilant when copy/pasting from another project's Dockerfile. It's possible the other project uses something your project will never need.

Minimize the number of layers

Each command in a Dockerfile creates a layer in the resulting image. Reducing the number of layers helps caching and can improve build times. A good approach to this is to group similar operations into a single command. Putting your apt-get update and apt-get install operations in a single RUN line is a good example of this:

RUN apt-get update && apt-get install -y python python-dev python-pip

You should also use the following tactic for installing your Python or Node dependencies. On one line ADD your dependency list file. On the following line change into that path and run the install command.

Python:

ADD requirements.txt /src
RUN cd /src && pip install -r requirements.txt

Node:

ADD package.json /src
RUN cd /src && npm install

Use common base images in Drone

As of Drone v0.4, standard base images like python:3.5 or golang are supported for build steps. Only on very rare occasions will you need to build a custom base image for your project. If you think your project might require one, talk it over with some of the other engineers on the team for insight. Using basic base images helps conserve storage space and reduce costs for running our build server.

Python: python:3.5

Web (Node): registry.vokal.io/web-testing

FROM node

ENV PHANTOMJS_VERSION 1.9.7

RUN \
  apt-get update && \
  apt-get upgrade -y && \
  apt-get install -y vim git wget libfreetype6 libfontconfig bzip2 socat && \
  mkdir -p /srv/var && \
  wget -q --no-check-certificate -O /tmp/phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2 https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2 && \
  tar -xjf /tmp/phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2 -C /tmp && \
  rm -f /tmp/phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2 && \
  mv /tmp/phantomjs-$PHANTOMJS_VERSION-linux-x86_64/ /srv/var/phantomjs && \
  ln -s /srv/var/phantomjs/bin/phantomjs /usr/bin/phantomjs && \
  git clone https://github.com/n1k0/casperjs.git /srv/var/casperjs && \
  ln -s /srv/var/casperjs/bin/casperjs /usr/bin/casperjs && \
  apt-get autoremove -y && \
  apt-get clean all
RUN npm install -g bower grunt-cli

Go: golang