7 Tips For Docker Compose Beginners
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.