Here are some basic tips and best practices for writing Dockerfiles, building Docker Images and using Docker in general. Feel free to add your suggestions with a pull request.

  • Create Dockerfiles with cache (of the layers) in mind.
  • Use empty lines, comments and backslashes ("\") for readability.
  • Keep each image layer "atomic".
  • Optimize containers (check fromlatest.io and imagelayers.io).
  • Containers are not Virtual Machines.
  • Think of creating your own private registry.
  • Use docker-compose.yml templates if you need permanent containers.
  • Be aware of the hub.docker.com agent version (different versions need different Dockerfile).
  • Group common operations under the same instruction.
  • Don't install useless software.
  • Keep images small and unique.
  • Search for similar public images before creating your own.
  • When you need software to install another software remove the first after the build.
  • Uppercase the Dockerfile instructions.
  • Split the Dockerfile instructions while developing your Dockerfile and merge them when you are ready to publish it.
  • Split multiprocess images to several images with one process per images.
  • Use ADD and VOLUME at the end of the Dockerfile (except if files are needed before).
  • If you have multiple Dockerfile steps that use different files from your context, COPY them individually, rather than all at once.
  • Prefer using an ENTRYPOINT always.
  • Install specific versions of software.
  • With COPY the directories are not copied, only their files.
  • When using a base image choose a specific tag (avoid default tag "latest").
  • Never map directly the public port inside a Dockerfile.
  • Prefer using the array syntax for CMD, ENTRYPOINT etc (CMD [...]).
  • Prefer the tiny base images (busybox, alpine, tinycore, baseimage etc).
  • Build your own base image when you want full control of the Dockerfile.
  • Things that do not change ofter should stay on top of the Dockerfile (eg MAINTAINER).
  • If you need to work constantly with local files use VOLUME and not ADD.
  • Test builds locally before triggering automated builds to the online docker registries.
  • Use Dockerfile for infrastructure and docker-compose for tasks (apps).
  • Regex used in Dockerfiles are from Go language.
  • Never do things like apt-get upgrade inside a Dockerfile.
  • Containers should model processes and not virtual machines.
  • Create local shortcut/aliases for common docker commands and workflows.
  • Be careful with volumes. When docker mounts folders on read-write mode your files may be deleted.
  • A volume will never be deleted as long as a container is linked to it.
  • Use shell scripts for complicated RUN commands on the Dockerfile as also as for starting processes on containers.
  • Running the same image multiple times does not add multiple images on the host disk (1x ubuntu:latest == 100x ubuntu:latest).
  • Avoid using a GUI. CLI makes it easier to understand the Docker philosophy.
  • Prefer running processes inside containers with a non ROOT user for security reasons.

Resources

See more at the official source of this blog post which is part of my presentation "Introduction to Docker for Developers".