This lesson is in the early stages of development (Alpha version)

Using Docker Compose

Overview

Teaching: -1 min
Exercises: -1 min
Questions
  • What is Docker Compose?

  • How can I use file-based container settings?

  • How do I run multiple containers at once?

Objectives
  • Create and use a Docker Compose file.

  • Run multiple (interacting) containers at once.

Brief Introduction to Docker Compose

Sometimes your settings for a container become more advanced. Sometimes you want to run multiple containers at once. These are tasks, where Docker Compose makes developing and using dockerized applications easier.

Verify the Docker Compose installation

Compose is already shipped with Docker for Windows and Mac. Linux users can use one of multiple ways of installing. The recommended way is:

$ pip install docker-compose

To verify your installation, use the following:

$ docker-compose -v
docker-compose version 1.28.4, build unknown

If you get a Permission Denied error message, your user account is probably not added to the docker group. In this case you need to either prepend the sudo command or add your user to the docker user group.

What is Docker Compose?

From the official wiki:

Compose is a tool for defining and running multi-container Docker applications.
With Compose, you use a YAML file to configure your application’s services.
Then, with a single command, you create and start all the services from your configuration.

Additionally, it is a good way to store Docker container configurations (in a file).

Why do we need Docker Compose?

More advanced Docker configurations might be unwieldy to use with only Docker. You may have multiple Dockerfiles for your multi-container application or complicated setups in general. This is where Docker Compose can help you tremendously. There will be a single YAML file that describes your setup and with a simple call of Docker Compose you are able to spin up your whole application with ease.

A complex Docker call like this

$ docker run -d \
         --name=GFZ_statping \
         -p 8080:8080 \
         --restart always \
         -v "$PWD/config.yml:/app/config.yml:ro" \
         -v "$PWD/services.yml:/app/services.yml:ro" \
         statping/statping

becomes this

$ docker-compose up -d

As already mentioned above, we need to write our configuration to a YAML file to make this possible. Every setting from the Docker call needs to be put into that file to achieve the same result.

version: "3.9"
services:
  GFZ_statping:
    image: statping/statping
    ports:
      - "8080:8080"
    volumes:
      - "$PWD/config.yml:/app/config.yml:ro"
      - "$PWD/services.yml:/app/services.yml:ro"
    restart: always

Writing a docker-compose.yml

We see some key-value pairs in this YAML file. We will go through them individually, while building the following example:

Note: We will use a web application, because it is (for this example) easier to set up as a demo

cd $PRJECTDIR
$EDITOR docker-compose.yml
version: "3.9"

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: {}

version

Provides information about the version of Docker Compose YAML. It is optional and mainly needed to support older Docker Compose clients.

services

Within this key all Docker containers managed by Docker Compose are listed. Only list containers that are related. Every project should have its own docker-compose.yml

$SERVICENAME

Gives every service a unique name. There are some limitations (e.g. no colons) to the name. Within a given service, all settings for this service are stored.

image

Defines the image to use. Only images from Docker registries like Docker Hub or GitLab Container Registry can be used here.

build

In case you build your own image, use this key. You can define a context to specify a working directory during build. Additionally, you can point to a Dockerfile to use.

services:
  backend:
    build:
      context: ./backend/api
      dockerfile: ./docker/Dockerfile
  frontend:
    build:
      context: ./frontend
      dockerfile: ./docker/Dockerfile

volumes

Defines a list, which specifies files and folders to persist beyond the lifetime of the containers and specifies persisted files and folders which should be mounted within the container.

restart

Defines the restart policy.

environment

Set environment variables within the Docker container. This is done during the start of the container.

depends-on

Sets one (ore more) services as dependency for another service. It will only start, if the dependency started successfully.

ports

Defines a list, which ports should be routed to the host.


The list above is far from being complete. It is possible to create very complex structures within Docker Compose.

Note: some IDEs can auto-complete and lint docker-compose.yml files (JetBrains IDEs, for example)

Starting Docker Compose

To start the containers, run

docker-compose up -d

You can now visit localhost:8000 to see the application running.

Sopping Docker Compose

docker-compose down

Key Points

  • Using Docker Compose makes developing and using dockerized applications easier most of the time

  • Use a docker-compose.yml to configure your container(s)

  • Use docker-compose up -d to start your container(s)

  • Use docker-compose down to stop your container(s)