Create Your docker-compose.yml File
In the last chapter, we saw how to use the command-line interface for Docker Compose. Now it’s time to learn how to create a docker-compose.yml
file.
Start by creating a docker-compose.yml
file at your project root. In this, describe all of the resources and services required to create your POC.
Describe Your First Service: db
Define the Version of Docker Compose
A docker-compose.yml
file always starts with the following information:
version: '3'
The version
argument tells Docker Compose which version we want to use. Here we’re using version three, which is currently the most widely-used version.
Declare the First Service and Its Image
We’re now going to declare our first service, which will create our WordPress stack!
services:
db:
image: mysql:5.7
Next, you need to describe your container. Here, we’re using the image
argument which defines the Docker image that we want to use.
Define the Volume in Order to Persist Your Data
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
Remember, earlier we saw that Docker containers are not created to run stateful services, and that a database is by definition a stateful service. However, you can use the volumes
argument, which lets you store all of the contents of the /var/lib/mysql
folder in a persistent disk, thereby locally storing our data on our host.
This description is present in the line db_data:/var/lib/mysql
. db_data
is a volume created directly by Docker which lets you write data to the host disk without specifying the exact location. You could also have used /data/mysql:/var/lib/mysql
, which would have worked just as well.
Define a Restart Policy for the Container
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
Since a container is, by definition, single-process, if it encounters a fatal error, it might just stop. In our example, if the MySQL server stops, it will restart automatically using the restart: always
argument.
Define Environment Variables
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
The MySQL image provided has several environment variables that you can use. For our example, we’re going to give the container the values of different passwords and users that should exist on this base. When you want to give environment variables to a container, you should use the environment
argument, just like we have done in the docker-compose.yml
file above.
Describe Your Second Service: WordPress
In the second service, we create a container that will contain everything we need to run our website with WordPress. This allows us to introduce two additional arguments.
services:
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
The first argument ( depends_on
) is for creating a dependency between two containers. This means that Docker will start the db service before starting the WordPress service. We want this to happen, as WordPress depends on the database to work correctly.
The second argument ( ports
) tells Docker Compose that we want to expose a port from our host machine to our container, making it externally accessible.
Here is the docker-compose.yml file in its final version:
version: '3'
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
db_data: {}
Run Your Docker Compose Stack
When you run your containers with the docker-compose up -d
command, you should get the following result:
$ docker-compose up -d
Creating network "my_wordpress_default" with the default driver
Pulling db (mysql:5.7)...
5.7: Pulling from library/mysql
efd26ecc9548: Pull complete
a3ed95caeb02: Pull complete
...
Digest: sha256:34a0aca88e85f2efa5edff1cea77cf5d3147ad93545dbec99cfe705b03c520de
Status: Downloaded newer image for mysql:5.7
Pulling wordpress (wordpress:latest)...
latest: Pulling from library/wordpress
efd26ecc9548: Already exists
a3ed95caeb02: Pull complete
589a9d9a7c64: Pull complete
...
Digest: sha256:ed28506ae44d5def89075fd5c01456610cd6c64006addfe5210b8c675881aff6
Status: Downloaded newer image for wordpress:latest
Creating my_wordpress_db_1
Creating my_wordpress_wordpress_1
When executing this command, Docker Compose starts by checking if we have the images required to run the stacks available locally. If not, it will download them from a registry, or build them via docker build
.
It will then launch two containers on your system. For our example, you can see the result by opening the following URL in your browser: http://127.0.0.1:8000
.
Let’s Recap!
You now know how to use the basic commands in Docker Compose, and create a docker-compose.yml
file to manage your Docker containers.
Here’s a recap of the arguments we’ve looked at in this chapter:
image
for specifying the source image for the containerbuild
for specifying the source Dockerfile to create the container imagevolume
for specifying the mountpoints between the host system and the containersrestart
to define how the container behaves if the process is stoppedenvironment
to define the environment variablesdepends_on
to state that the container depends on another containerports
to define the available ports between the host machine and the container
Join me in the next chapter to practice using Docker Compose.