Exercise

In this exercise, we will illustrate the use of Docker Compose and launch the Voting App. This application is widely used for presentations and demos, it’s a good example of a simple micro-services application.

Overview

The Voting App consists of several micro-services, those used for version 2 are the following:

Voting App architecture

  • vote-ui: front-end allowing a user to vote between 2 options
  • vote: back-end receiving votes
  • result-ui: front-end for viewing results
  • result: back-end making results available
  • redis: redis database where votes are stored
  • worker: service that retrieves votes from redis and consolidates results in a postgres database
  • db: postgres database where results are stored

Retrieving GitLab repos

Run the following commands to retrieve the repo of each microservice as well as the configuration repo:

mkdir VotingApp && cd VotingApp
for project in devops vote vote-ui result result-ui worker; do
  git clone https://gitlab.com/voting-application/$project
done

The compose.yaml file format

Several files, in Docker Compose format, are available in devops/compose:

  • compose.dev.yaml is used to launch the application in a development context
  • compose.yaml is used to build images for each microservice in a production context

Launching the application

From the devops/compose directory, launch the application using the following command (the compose.yaml file will be used by default):

docker compose up -d

The steps performed when launching the application are:

  • creation of front-tier and back-tier networks
  • creation of db-data volume
  • building images for vote-ui, vote, result-ui, result, worker services and pulling redis and postgres images
  • launching containers for each service
ℹ️
A reverse proxy based on Traefik will also be launched but it won’t be used in this exercise.

Launched containers

With the following command, list the containers that were launched and ensure they are all in Up status:

docker compose ps

Created volumes

List volumes with the CLI, and verify that the volume defined in the docker-compose.yml file is present.

docker volume ls

The volume name is prefixed by the directory name where the application was launched.

DRIVER    VOLUME NAME
local     compose_db-data
...

By default, this volume corresponds to a directory created on the host machine.

Created networks

List networks with the CLI. The two networks defined in the docker-compose.yml file are present.

docker network ls

As with the volume, their names are prefixed by the directory name.

NETWORK ID     NAME                 DRIVER    SCOPE
71d0f64882d5   bridge               bridge    local
409bc6998857   compose_back-tier    bridge    local
b3858656638b   compose_front-tier   bridge    local
2f00536eb085   host                 host      local
54dee0283ab4   none                 null      local

Note: as we are in a single-host context, the driver used for creating these networks is of bridge type. It allows communication between containers running on the same machine.

Using the application

We can now access the application:

we make a choice between the 2 options from the voting interface at http://HOST_IP:5000

Vote interface

we view the result from the results interface at http://HOST_IP:5001

Result interface

Note: replace HOST_IP with localhost or with the IP address of the machine where the application was launched

Scaling the worker service

By default, one container is launched for each service. It’s possible, with the –scale option, to change this behavior and scale a service once it’s launched.

With the following command, increase the number of workers to 2.

docker compose up -d --scale worker=2

Verify that there are now 2 containers for the worker service:

docker compose ps

Notes: it’s not possible to scale the vote-ui and result-ui services because they both specify a port, multiple containers cannot use the same host machine port

Removing the application

With the following command, stop the application. This command removes all previously created elements except volumes (to avoid losing data)

docker compose down

To also remove the volumes used, add the -v flag:

docker compose down -v