Docker compose – how to orchestrate different containers

Docker compose
The advent of microservices architecture and DevOps methodology has created the need for virtualization at the operating system level. Using Docker Compose we can create even very complex container-based applications and manage interdependencies. Let's find out through an example based on Wordpress how to do it.

Share

Share on facebook
Share on linkedin
Share on twitter
Share on email
Reading time: 5 minutes

Docker technology has made it possible in recent years to simplify the work of developing and deploying various applications. Especially with the advent of microservices and DevOps, creating containers to isolate different services has been a winning choice. As we saw in article Introduction to Docker, Docker has several features and potentialities. However, in the other article we focused on creating a single container using the Dockerfile. Since many modern applications require multiple components, setting up an entire project on single Dockerfiles can be very complicated. Let’s see how Docker Compose can help in managing multiple interconnected services.

Why use Docker Compose

Nowadays any software is composed of several components. For example, a website built with WordPress needs a service to run the platform, a database and a web server (e.g. nginx). These 3 components must be active at the same time and must act on a network that puts them in communication with each other. If we analyze other software, the situation can become much more complicated. In recent years, based on the divide and conquer paradigm, applications are developed with a microservice architecture. So, you don’t build a “mega” software that contains the whole application, but you develop many small modules. Each module has a specific task and communicates with other modules when necessary. In this way, the application can grow as you go, and maintenance can be targeted to the modules of interest. Finally, the entire project can be deployed on different servers to optimize performance.

These examples show how in any application you need to orchestrate the various components/services appropriately. While it is very easy to customize containers with Docker, it is not as easy to manage interdependencies. In fact, the developer and/or system administrator would have to build the various images, create the necessary networks and, finally, run the application through a series of Docker commands in a predetermined order. The chances of human error throughout this process increase exponentially. Therefore, you need to automate the process.

Docker Compose is a tool for defining, and running multi-container applications. Containers, also called services, are described in a YAML file. Their relationships are also defined. Docker Compose parses this file and executes the commands defined within it. But that’s not the only functionality of this tool. We can also stop and restart the whole project or a single container, read the log of various running containers, view the status of a specific container. Since each Compose file defines a project, it is possible to isolate different projects and analyze their coexistence on the same infrastructure.

Docker Compose file versions

As we mentioned Docker Compose needs a YAML file to describe the containers to be managed. There are several versions that have been released over the years. It is possible to use one of the versions below. Nevertheless, we suggest you use the latest one available.

Version 1

Version 1 is the oldest version. All YAML files that do not specify the version are considered to belong to this type. Beware that in future releases it might be removed as it is already deprecated. This version also has some disadvantages:

  • version 1 files cannot declare named services, volumes, or build arguments
  • container discovery is only enabled using the links flag

Version 2

In order to define that you want to use version 2, you have to specify as value of the version field a value equal to 2 or 2.x. Compared to the previous version, it introduces some changes that do not allow direct portability from version 1. In fact, in version 2 all containers are on a default application-specific network and containers can be discovered by the hostname specified by the service name. The links attribute is made redundant, while the depends_on flag is introduced, allowing dependencies between containers to be specified.

Version 3

The latest available version is 3 and must be specified with the value 3 or 3.x. In this version some options, already deprecated in version 2, have been removed (e.g. volume_driver, volumes_from). A deploy key used for deploying and running services on Docker Swarm is introduced.

Example of a docker compose with WordPress

To better understand the definition of services in a Docker Compose file we’re going to analyze an example very useful for those who develop and manage websites. In particular we will see a WordPress project.

Step 1: Create the project

First you need to create the project. To do this simply create a directory with the name of the project such as my_wordpress.

This directory will be the context for the application image and should, as seen in the recommendations for the Docker file in article X, contain only the resources strictly necessary for the image.

Step 2: Create the docker compose file

Since this project will only need to contain the services needed to run a WordPress site, the folder will only contain the docker-compose.yml file. No other resources will be needed. In the file we will describe the necessary services as shown below.

version: '3.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: {}
 

Analysis of the Docker Compose file

Let’s analyze in detail the various items that we have introduced in the example.

As mentioned earlier at the beginning of the file you need to specify the version of the Docker compose file. In this case we specify that the version is 3.3. But if you want to be more general you can use simply 3.

Since you are using version 3 you have to define the services. In the case of a WordPress installation we can define 2 services: one related to the database and the other to WordPress. For each service we have to assign a name to our liking. The container name, if not specified otherwise by the container_name property, will be the project name concatenated with the service name.

For each defined service it is necessary to specify on which image it should be built. In the analyzed case we use images already available on the Docker Hub. For the database we will use a mysql image related to version 5.7, while for WordPress the last available image. At the time of writing this article, the image includes Apache, PHP version 7.4 and WordPress version 5.6. If instead you want to use an image defined by us through a Dockerfile, you must specify through the build property the path where the Dockerfile is contained and the files that will be used.

Another property that is usually used is environment. This attribute specifies the environment variables of the container. This allows you to customize the container to suit your needs. In this example, environment variables (defined in the image documentation) are used to set the credentials for mysql and the name of the database to be used for WordPress.

The depends_on attribute indicates the dependencies between containers so that a container is not started until the container it depends on is available. In this case, for the WordPress site to work properly, the service must not be activated until the mysql database is available.

Each container by definition is an isolated environment. In order for it to communicate with other containers or to be accessed via host ports, it is necessary to specify the expose and ports properties. Expose is used to listen to the container on certain ports. These can be defined in the image Dockerfile or also in the Docker Compose file. Only containers belonging to the same project, or registered on the same network, will be able to start with the referenced container on that port. Differently, the ports property maps host ports to container ports.

To ensure that containers restart automatically if a service interruption occurs, it is advisable to enter the restart: always command.

Finally, to properly save the database data we need a volume. In fact, as we said in article XX, state changes are saved inside the container. To define a volume we need to specify it under volumes, while to use it in the container we need to associate the volume with a path inside the container. In the example we associated the volume named db_data to the path /var/lib/mysql where data from mysql is saved.

This is one of many examples. You can find more in the official documentation. The advice is to start from these examples and modify them according to your project needs.

Recommended Readings

More To Explore

Wordpress

Manage Advanced Custom Fields and integrate them in a WordPress plugin

During the development of a Wordpress website or plugin, the need arises to track some information in a structured way. Using the Advanced Custom Fields plugin, it is possible to create custom fields in a simple and intuitive way. Let’s discover how to generate them and integrate them into the pages of our site or into the logic of our plugin.

Wordpress

Create a settings page for a WordPress plugin

Every Wordpress plugin needs some information from the administrator to work at its best. In this article we will see how to add a settings page and adapt it to our needs.

Leave a Reply

Your email address will not be published. Required fields are marked *

Design with MongoDB

Design with MongoDB!!!

Buy the new book that will help you to use MongoDB correctly for your applications. Available now on Amazon!