This article will look at deploying multi-container applications using Docker Compose.
Docker Compose makes our life easier, and at the end of this post, you will have a clear vision of why and how it happens.
To make our article richer, we will go through step-by-step how to deploy WordPress using Docker, especially docker-compose.
Through this process, you don’t have to create your dockerfile to use WordPress. Instead, you can pull the official images from the Docker Hub. Let’s see how easy to deploy it, and we also go through some helpful command lines to use along with docker-compose.
Deploying Apps with Docker Compose
Modern apps deployed in the cloud contain multiple minor services that talk between them to assemble a helpful app. In the computing world, this concept is known as “microservices.” For example, below some of the models might be an application with the following services:
Back end for process request (API)
CMS (WordPress)
Web front-end
Store
Machine Learning Tasks
Logging
Reverse Proxy
Get all of these together, and you have a real scenario application.
Deploying and composing lots of small microservices like these can be challenging. This is where Docker Compose comes into play.
In our last article about containers, you learned that Docker provides us with a lot of features that you can perform through the command line. However, for a complex environment that depends on multiple parts, that could be tricky to handle all pieces together. So, instead of having Shell Scripts with many Docker commands inside, you can use docker-compose to build your description of how docker-compose should create the application.
Once the application runs, you can handle its entire lifecycle with a straightforward set of commands. Also, you can store and control the configuration file in a version control system like Git.
That’s the concept. Let’s explore this more in-depth.
To make our example most close to a real scenario, where you can learn and apply and take advantage of the Docker benefits. Our example will deploy a simple WordPress to host our Blog.
What you need about Docker Compose
In the beginning, the docker-compose was created by a company called Orchard, and it was the most helpful way to handle multi-container Docker apps. It was a Python tool that sat on top of Docker and let you determine a whole multi-container application, like WordPress, in a single YAML file.
And because we only have one file, it is easier to share with others. Anyone can reuse your YAML file and download the Docker Images from the Docker Hub or any order Remote Registry.
You could then deploy and manage the lifecycle of any application.
Behind the scenes, it would use and read the YAML file and Docker to deploy and control the applications via the Docker API. It was a good thing.
Compose is an external Python binary you must install on a Docker host. You describe multi-container (microservices) applications in a YAML file, give the YAML file to the docker-compose command line, and Compose deploys it via the Docker API.
Time to learn it in practical exercises.
Installing Compose
Check the version of docker-compose:
docker-compose --version
If you see this error message:
"docker compose command not found"
It means that you need to install the docker-compose binary on your computer.
On Linux:
curl -SL https://github.com/docker/compose/releases/download/v2.12.2/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
On Windows:
If you installed Docker Desktop/Toolbox for either Windows or Mac, you already have Docker Compose! Check here to install.
Compose files
Compose uses YAML files to define multi-service applications. YAML is a subset of JSON, so you can also utilize JSON. However, all the examples in this article will be YAML.
In your project folder, you can create a file called docker-compose.yml. That name is the default name. So, if you don’t specify the name, the docker-compose binary will automatically look up for that file. You should add the argument -f in your command line to set a different name.
The docker-compose file in our example will start the WordPress along with a MySQL database, which is required for any WordPress server.
Docker Compose and WordPress
Create a file docker-compose.yml on your computer with the content below:
version: '3.1'
services:
wordpress:
image: wordpress
restart: always
ports:
- 80:80
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: exampleuser
WORDPRESS_DB_PASSWORD: examplepass
WORDPRESS_DB_NAME: exampledb
volumes:
- ./volumes/wp:/var/www/html
db:
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: exampledb
MYSQL_USER: exampleuser
MYSQL_PASSWORD: examplepass
MYSQL_RANDOM_ROOT_PASSWORD: '1'
volumes:
- ./volumes/db:/var/lib/mysql
Also, create the directories at the same location as docker-compose.yml:
/volumes/wp
/volumes/db
Let’s see some basics before:
The “docker-compose up” expects the name of the Compose file to be docker-compose.yml. If your Compose file has a different name, you need to specify it with the -f flag. The first thing to note is that the file has top-level keys:
version
services
volumes
The version key is required, and it’s always the first line at the root of the YAML file.
What do you need to specify the version here?
Because the version represents the version of the Compose file structure (essentially the API), you should generally use the latest version.
Note that the version key does not determine the version of Docker Compose or the Docker Engine.
Tip: If you are wondering which version of the Yaml file is compatible with the Docker Compose, you can check it on the official website.
The Docker Compose version that we are using for this example is 3.1.
Docker Compose Services
What does the service key mean on the docker-compose file?
The services key goal is to define each application (microservice), you can determine many applications that you need, and there is no limitation.
Looking more closely, you can notice that there are two services declared in our example: worpress and db.
The wordpress service will contain the wordpress itself and its dependencies that needs to run, like Apache.
All data that WordPress needs to store is on a database. WordPress can use any SQL Database. In our case, this service starts up one MySQL server.
Define Volumes on Docker Compose
Behind the scene, Docker will store all data generated by our WordPress on the location that we define on key volumes.
The volumes is a good feature because they allow you to choose where Docker should store the files. It means you still have the data even if you delete the container. Later, you can create a new container and reuse the same data if it’s the case. So, it is an approach to persist data.
Another good use case for Docker Volumes is that if you change the WordPress container version, for example, from version 5.7 to 6.1, you will not lose your data.
But I don’t specify a path to mount one folder from my computer. So the Docker will be stored by default in its installation folder. And it’s a little tricky to figure out which folder would be specific to a container.
On Linux, for example, the default installation of Docker and the path for Volumes:
/var/lib/docker/volumes
How does Docker Compose naming the containers?
When you start your container using docker-compose, it’s important to note that it follows a specific logic to name the container from your Yaml file.
The name of the keys will be part of the container names, so in our example, Docker Compose will create the container with the following names:
docker_wordpress_1 docker_db_1
Let’s continue to analyze our docker-compose.yml file.
What the port key on the Yaml file means?
It maps port 80 inside the container (-target) to port 80 on the host.
What does that map mean?
Traffic sent to the Docker host on port 80 will be directed to port 80 on the container because the WordPress inside the container listens on port 80.
Running WordPress on Docker Compose
In the same directory where you have docker-compose.yml file, you can run the following command to start our WordPress.
docker-compose up &
Alternatively, you can use the -d flag to execute the app in the background. Like:
docker-compose up -d
The “docker-compose up” expects the name of the Compose file to be docker-compose.yml. If your file has a different name, specify it with the -f flag.
It’ll take a few seconds for WordPress to come up, and the output can be pretty verbose. You may also have to hit the Enter key when the deployment completes.
We’ll describe what occurred in a second, but first, let’s analyze the docker-compose command.
The docker-compose up is the most familiar way to start a Compose application (we’re creating a multi-container application represented in a Compose file). It creates or pulls all dependencies (images), generates all volumes, and starts all necessary containers.
Now, you can open your web browser on http://localhost:80 and access WordPress!
How to check the Running Containers
To list the containers running after you execute the “docker-compose up”, you can run the following command:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
45eb5c635989 wordpress "docker-entrypoint.s…" 3 weeks ago Up 5 days 0.0.0.0:80->80/tcp, :::80->80/tcp docker_wordpress_1
9c2028941a97 mysql:5.7 "docker-entrypoint.s…" 3 weeks ago Up 5 days 3306/tcp, 33060/tcp docker_db_1
You can see both containers, the commands they are running, their current state, and the network ports they are listening on.
You can use “docker-compose top” to list the processes inside each service (container).
docker_db_1
UID PID PPID C STIME TTY TIME CMD
----------------------------------------------------------------
systemd+ 524336 524257 0 Oct19 ? 00:07:16 mysqld
docker_wordpress_1
UID PID PPID C STIME TTY TIME CMD
------------------------------------------------------------------------------
root 524353 524319 0 Oct19 ? 00:00:22 apache2 -DFOREGROUND
www-data 524526 524353 0 Oct19 ? 00:00:00 apache2 -DFOREGROUND
www-data 524527 524353 0 Oct19 ? 00:00:00 apache2 -DFOREGROUND
www-data 524528 524353 0 Oct19 ? 00:00:00 apache2 -DFOREGROUND
www-data 524529 524353 0 Oct19 ? 00:00:00 apache2 -DFOREGROUND
www-data 524531 524353 0 Oct19 ? 00:00:00 apache2 -DFOREGROUND
The PID (Process ID) numbers above are the PID numbers seen from the Docker host (not from within the containers).
How to stop the container without losing the data?
Sometimes, you want to stop the container and but at the same time, you need to keep the data if you need to use the container again. For example, you can use the following command:
docker-compose stop
As you can notice, stopping a Compose application does not delete the application definition from the system. It just stops the containers. You can confirm this with the docker container ls -a command.
docker ps -a
You can delete stopped containers with “docker-compose rm“. The command will delete the applications’ containers and networks but will not remove volumes or images.
Note: If you want to stop and delete the containers, you can execute the command below:
docker-compose down
How to Restart the containers
docker-compose restart
Commands Summary
- docker-compose up is the command to deploy any app. It expects the docker-compose.yml file to be called, but you can specify a custom filename with the -f flag. It’s common to start WordPress in the background with the -d flag.
- docker-compose stop will stop all containers in a Compose app without deleting them from the system. You can smoothly restart the app with docker-compose restart.
- docker-compose rm will delete a stopped Compose app. It will delete containers and networks, but it will not remove volumes and images.
- docker-compose down will stop and delete a running Compose app. It deletes containers and networks but not volumes and images.
- docker-compose restart will restart a Compose app that has been stopped with docker-compose stop. If you have made changes to your Compose app since stopping it, these changes will not appear in the restarted app. You will need to redeploy the app to get the changes.
Conclusion
In this article, you learned how to deploy and manage a multi-container application using Docker Compose and how to use it with WordPress.
Docker Compose is a Python application that you install on top of the Docker Engine. It lets you specify multi-container apps in a single declarative configuration file (docker-compose.yml) and deploy it with a single command.
Compose files can be JSON or YAML, and they describe all of the containers, networks, volumes, and secrets that an application demands. You then provide the file to the docker-compose command line tool and Compose Docker to deploy it.
Once the app is deployed, you can control its whole lifecycle using the many docker-compose sub-commands.
You also noticed how volumes have a separate lifecycle from the rest of WordPress and can be used to mount changes directly into containers.
Docker Compose is famous among developers, and the Compose file is an excellent source of application documentation — it defies all the services that make up any app, the images they use, ports they expose, networks and volumes they utilize, and vastly more. As such, it can support bridging the gap between dev and ops. However, you should also treat your Compose files as if they were code. This means, among other items, keeping them in source control like Git.