Blog

Dockerize Your Entire Solution

Published on 2020-03-20.
"How can I run an entire solution on every platform?" – An introduction to Docker Compose.

This article is about showing the benefits of Docker Compose for the development and the deployment of multi-service solutions consisting of different applications, databases, web services, or even entire out-of-the-box systems.

So, let's start with a brief overview of Docker Compose.

Docker Compose is a tool that allows you to define and run multi-container Docker solutions. You can use it every time you need to run applications consisting of more than one component each running in a dedicated Docker container. As an example, the following diagram depicts the composition of two Docker containers: A WordPress website, and the corresponding MySQL database:

Docker Compose

On the example above, you'll explore how you can step-by-step get familiar with Docker Compose. You will learn about the definition of composed applications, as well as how to run them with merely one single command.

Let us first briefly walk through the main features of Compose:

Feature 1 - Works in every environment
Compose works in all environments, from development, to testing, to staging, to finally production. It is also perfectly working in continuous integration workflows.

Feature 2 - Caching of configuration
Compose caches the configuration, so when you restart an unchanged service, it re-uses the existing containers. This enables you to make changes to your environment very precisely and in less time.

Feature 3 - Variable configuration
Compose supports variables in the Compose file, which you can use to customize your composition for different environments.

Feature 4 - Isolation of environments
Compose uses a project name to separate environments from each other. That helps you to create multiple copies, or in case you want to name the project to a unique build number.

Feature 5 - No loss of data during restart
Compose preserves all volumes used by your services and copies the volumes from the previous container to the new container. So, your data will not get lost.

Next, we will explore some common use cases of using Compose.

Use Case 1 - Development environments
Compose offers the ability to run an application in an isolated environment and let you easily interact with it. So, you can define and configure the setup of your entire application – including databases, queues, web services, etc. – and run it with one single command.

Use Case 2 - Automated testing
Compose helps you to define, configure and run automated testing by deploying test environments. You can use that e.g. to assure quality during any continuous deployment or continuous integration process. After the tests have been performed, Compose takes care for destroying the isolated testing environment.

Let's get back to the example of WordPress.

The following code sample shows the docker-compose.yml definition:

version: '3.3'

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
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
MYSQL_ROOT_PASSWORD: somewordpress

volumes:
db_data:

The compose definition will be defined in detail in the following table:

Level 1Level 2Level 3 Description
versionVersion of the Compose definition
servicesSection which contains the definition of all Docker containers which must be built and deployed
wordpress / dbSection for wordpress or db service (custom name)
depends_onReferences a dependency to another defined service
imageReferences an available Docker image which will be used during building process
portsMapping of the external available port (first number) to the internal port (second number)
restartFlag whether the service should be automatically restarted after stopping
environmentSection which contains all necessary environment variables which will be used inside the Docker container
volumesReferences the volume section
volumesSection which defines the available volumes


Starting and Stopping of all services

Starting the application including both Docker containers in pretty simple and you can do it from the command-line interface (CLI) by typing the following command:
docker-compose up -d

The parameter -d determines that the containers will run in background mode.

If you want to stop the entire application, type the following command to stop and remove all corresponding Docker containers:

docker-compose down

You can see the running containers by entering the following command:

docker ps

Docker Compose

In the list of currently running containers, you can see that their names contain the prefix called "wordpressmysqlsample" and a suffix called "1".
The suffix is a number indicating the number of instances of a service; we will talk about that in the next chapter about scaling services.
The prefix of the container gets the name of the folder, which contains the YAML file. But you can customize the prefix by utilizing the parameter "-p" like in the following example:

docker-compose -p myblog up -d

Docker Compose

As you can see, the prefix now changed to "myblog".

Scaling of Services

When it comes to the point that one instance of a service is not able to process the incoming requests, you can scale the service up. That means that in parallel to the already running service instance, you can start additional services instances to share the load. Since both containers work on the same port, we need to introduce a load balancer to forward the incoming calls to the one or the other service instance.

We will add for this purpose the dockercloud/haproxy ready-to-use Docker image, which will distribute the requests in a round-robin fashion to the service instances. The following listing contains the service "load-balancer" which references the "wordpress" image and also takes care for the definition of the ports:

version: '3.3'

services:
wordpress:
depends_on:
- db
image: wordpress:latest
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
MYSQL_ROOT_PASSWORD: somewordpress
load-balancer:
image: dockercloud/haproxy
links:
- wordpress
volumes:
- /var/run/docker.sock:/var/run/docker.sock
ports:
- "8000:80"

volumes:
db_data:

After starting, you can now see the additional load balancer container running:

Docker Compose

You can easily scale up the available WordPress containers to two instances by entering the following command:

docker-compose -p myblog scale wordpress=2

When you now look at the list of currently running Docker containers, you will see two instances of the WordPress container each one having a different number as suffix of the container name:

Docker Compose

In order to properly shut down all of the services, it is crucial to use the name you gave when starting it, like:

docker-compose down -p myblog

Finally, I would also share interesting and essentials resources regarding the topics which has been covered in this article, such as:

Overview of Docker Compose

Docker Images of haproxy