Best Practices When It Comes to Writing Docker Related Files
Tags: beginners, docker, devops, webdev
Published: 2018-10-03 13:05:15

---
title: Best Practices When It Comes to Writing Docker Related Files
published: true
description: "Here's a few patterns and little things I've picked up after using Docker since 2014. These help maintain Docker driven apps."
tags: beginners,docker,devops,webdev
cover_image: https://thepracticaldev.s3.amazonaws.com/i/jgs89llinxle5161jqeh.jpg
canonical_url: https://nickjanetakis.com/blog/best-practices-when-it-comes-to-writing-docker-related-files
---

**This article was originally posted on June 19th 2018 at: https://nickjanetakis.com/blog/best-practices-when-it-comes-to-writing-docker-related-files**

---

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.

## Dockerfile

- 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.*

## docker-compose.yml

- 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..

## .dockerignore

- 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`

## Example Apps for Popular Web Frameworks

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](https://github.com/nickjj/docker-web-framework-examples).

##### Fully working Docker Compose based examples that you can reference:

- [Flask](https://github.com/nickjj/docker-web-framework-examples/tree/master/flask)
- [Node / Express](https://github.com/nickjj/docker-web-framework-examples/tree/master/node)
- [Phoenix](https://github.com/nickjj/docker-web-framework-examples/tree/master/phoenix)
- [Rails](https://github.com/nickjj/docker-web-framework-examples/tree/master/rails)
- [Webpack](https://github.com/nickjj/docker-web-framework-examples/tree/master/webpack)

If you don't see your favorite web framework listed above, [open up a PR](https://github.com/nickjj/docker-web-framework-examples/blob/master/CONTRIBUTING.md)! 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!**