Learn Docker With My Newest Course

Dive into Docker takes you from "What is Docker?" to confidently applying Docker to your own projects. It's packed with best practices and examples. Start Learning Docker →

Best Practices When It Comes to Writing Docker Related Files


Here's a few patterns and little things I've picked up after using Docker since 2014. These help maintain Docker driven apps.

Quick Jump: Dockerfile | docker-compose.yml | .dockerignore | Example Apps for Popular Web Frameworks

Update in 2021: This article was originally posted in mid-2018 and in mid-2021 I gave a talk at DockerCon which goes into way more detail, plus I’ve had a few changes of opinion since then. You may want to skim this article and then check out the live demo video and blog post from DockerCon.

Everything listed below is based on personal experience and opinions. These are things that have worked well for me and the clients I’ve worked with while freelancing over the years.

It’s also worth mentioning that this list always changes based on new experiences and I’ll be updating this post as new patterns / styles emerge.


  • Use Alpine as a base image unless you can’t due to technical reasons
  • Pin versions to at least the minor version, example: 2.5-alpine not 2-alpine
  • Add a maintainer LABEL to keep tabs on who initially made the image
  • Only include ARG and ENV instructions if you really need them
  • Use /app to store your app’s code and set it as the WORKDIR (if it makes sense)
  • When installing packages, take advantage of Docker’s layer caching techniques
  • If your app is a web service, EXPOSE 8000 unless you have a strong reason not to*
  • Include a wget driven HEALTHCHECK (if it makes sense)
  • Stick to the [] syntax when supplying your CMD instructions

* This is explained in more detail below under the docker-compose.yml section.


  • List your services in the order you expect them to start
  • Alphabetize each service’s properties
  • Double quote all strings and use {} for empty hashes / dictionaries
  • Pin versions to at least the minor version, example: 10.4-alpine not 10-alpine
  • Use . instead of $PWD for when you need the current directory’s path
  • Prefer build: "." unless you need to use args or some other sub-property
  • If your service is a web service, publish port 8000 unless it doesn’t make sense to
Alphabetizing your service’s properties, really?

Yep. Some services require having a bunch of properties and not giving them a specific order means you’ll likely order things in different ways across projects or even services.

It’s just 1 more thing to think about, but by having them alphabetized you no longer have to waste brain cycles grouping things up manually and you can scan a list of properties quickly.

Exposing and Publishing on port 8000?

That last one requires an explanation. I work with Flask, Rails, Phoenix and Node apps on a pretty regular basis. Each of these use different ports by default for their app server.

Rails uses 3000, Flask uses 5000, Phoenix uses 4000 and most Express apps use 3000.

When it comes to accessing these services in your browser, it’s confusing because you always think, wait is it localhost:3000 or localhost:4000?

By defaulting to 8000 for your web services there’s no more second guessing yourself. If you have a multi-service app then increment the port by 1, such as 8001, 8002, etc..


  • Don’t forget to create this file :D
  • Don’t forget to add the .git folder
  • Don’t forget to add any sensitive files such as .env.production

I’ve put together a few example applications that stick to these best practices. You can find them all on https://github.com/nickjj/docker-web-framework-examples.

Fully working Docker Compose based examples that you can reference:

If you don’t see your favorite web framework listed above, open up a PR! This repo is meant to be a community effort where we can work together to make high quality example apps that demonstrate Dockerizing popular web frameworks and libraries.

What are some of your best practices? Let me know below!

Free Intro to Docker Email Course

Over 5 days you'll get 1 email per day that includes video and text from the premium Dive Into Docker course. By the end of the 5 days you'll have hands on experience using Docker to serve a website.