7 Tips For Docker Compose Beginners

August 5, 2020
Improve your docker-compose.yml files

This is not rules, it's just tips from my personal experience with Docker, that you can use if you'd like.

1. Using restart: unless-stopped

To make sure the container is started automatically every time the host reboots, or the docker service is started, add restart: unless-stopped to all your containers.

version: '3.8'

services:
  web:
    image: nginx:1.19.1
    restart: unless-stopped
    ...

2. Don't use unnecessary links

When containers are in the same docker-compose file, and there is no network specified, they are all created on the same default network, so links are not needed.

From docker-compose documentation:

Links are not required to enable services to communicate - by default, any service can reach any other service at that service’s name.

version: '3.8'

services:
  web:
    image: nginx:1.19.1

  db:
    image: mariadb:10.5.4
    links:
      - web # Unnecessary.

3. Don't use latest tag (or no tag)

(At least on production and test environments)

While there may be some exceptions for this, generally I wouldn't use it.

You want to easily track which version (tag) you have running, and it will most likely cause different versions for different setups, which can cause errors.

So instead of using nginx:latest (or just nginx which defaults to the latest tag) - use a specific version like nginx:1.19.1

4. Use specific versions

For instance, dont just use php:7.4, instead the "full" version: php:7.4.8.

I ran into an issue because of this, I was using php:7.2 and suddenly when I setup a new instance, it didn't work. The problem was that ssmtp was unmaintained and couldn't be installed in the Dockerfile, so the build failed. Because the php:7.2 was pointing to a newer version which was built on a newer Debian version where ssmtp was removed.

You can probably imagine how frustrating it is when it works on one machine but not the other, with the exact same setup.

5. Use an .env file

Docker-compose automatically reads the .env file in the same directory as the docker-compose.yml file.

This means you don't have to "hardcode" your secrets into your docker-compose file, which is not only better for security, but also more flexible for other environments. Your .env variables can be used for more than secrets, but always make sure to add the file to your .gitignore.

.env

MYSQL_ROOT_PASSWORD=password

docker-compose.yml

version: '3.8'

services:
  db:
    image: mariadb:10.5.4
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}

6. Public directory

Make sure to always use a public directory, so you don't expose your docker-compose.yml or other super secret files to the world wide web.

version: '3.8'

services:
    web:
        image: nginx:1.19.1
        volumes:
            - "./config/nginx.conf:/etc/nginx/conf.d/domain.tld.conf"
            - "./src:/app" # `./src/public` will be mapped to `/app/public`
        ...

7. Using unnecessary expose

The expose option doesn't expose ports to the host, they'll only be accessible to linked services.

In this example, the MariaDB port 3306 is already accessible from the "web" container without the expose option.

version: '3.8'

services:

  web:
    image: php:7.4.16
    ...

  db:
    image: mariadb
    expose: 3306 # Unnecessary.
    ...

That's it. Feel free to share more tips in the comments.

Also, if you're on Discord, you're welcome to join the Docker server here.

Follow RSS/Atom Feed