Author avatar

Kimaru Thagana

Multi-Container App Management Using Docker-Compose

Kimaru Thagana

  • Sep 30, 2020
  • 6 Min read
  • Sep 30, 2020
  • 6 Min read
IT Infrastructure
Container Management


Containerization of apps with Docker is a fast-growing practice within the DevOps community. As apps get more complex, it requires more skill and robustness to manage them.

An easy management paradigm is separation of concerns. This is where the designer of a system creates logical layers that are separate but interdependent. With Docker, this is possible with the ability to separate an app into several containers.

This guide will explore multi-container apps and how you can use Docker Compose to manage the running of these containers.

It is assumed that you have at least beginner knowledge of Django apps and Docker. A guide that introduces Docker can be found here.

Docker Compose

Docker Compose is a tool for defining and running multi-container apps of any kind. To get started, Docker Compose needs to be installed. To install, run the command

1pip install docker-compose

Docker Compose directives are written in YAML format and are hosted in a file commonly named docker-compose.yml. Common Docker Compose commands include:

  • docker-compose up --build builds the images for every service defined in the docker-compose.yml file and run the containers in the predefined order.

  • docker-compose down --volumes removes all the containers built by your compose script as well as any storage volumes.

  • docker-compose ps lists all currently active containers.

  • docker-compose stop halts the running of the currently active containers.

    To further explore more Docker Compose commands, follow this guide.

Sample Script

For this sample script, suppose you are designing a Docker Compose file for a Django microservice app that is to be deployed to production and managed using Docker.

The setup involves three containers: an app container that runs the Django app, a Postgres container that runs the database, and an NGINX container that serves the app.

There are also static storage volumes where data and static files are stored. Since there are several containers at play, there should be an order in which they start up. Docker Compose addresses this with the depends_on directive. The directive informs Docker Compose which containers should start running before others can be executed.

In the sample script below, the common Docker Compose directives that have been discussed previously are put into practice.

1version: '3.7'
4  nginx: # service name
5    build: ./nginx # location of the dockerfile to build the image for this service
6    ports: # host:container- Bind the container port(80) to the host port(1339) Any traffic from the host via port 1339 will go to the docker container via port 80 
7      - 1339:80 
8    volumes: # define location where static files will live
9      - static_volume:/home/app/microservice/static
10    depends_on:
11      - web # web should be up and running for nginx to start
12    restart: "on-failure" # restart nginx container if it fails
13  web:
14    build: . #build the image for the web service from the dockerfile in parent directory
15    # issue commands to the application n the container
16    command: sh -c "python makemigrations &&
17                    python migrate &&
18                    python collectstatic &&
19                    gunicorn django_microservice.wsgi:application --bind${APP_PORT}"
20    volumes:
21      - .:/microservice:rw # map data and files from parent directory in host to microservice directory in docker containe
22      - static_volume:/home/app/microservice/static
23    env_file: # set the location and name of the env file to use when building the containers
24      - .env
25    image: django_microservice # image name
27    expose:
28      - ${APP_PORT} # internally expose the given port to other containers within the docker network
29    restart: "on-failure"
30    depends_on:
31      - db # web will only start if db is up and running
32  db: # service name
33    image: postgres:11-alpine # base image from dockerhub
34    volumes:
35      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
36      - postgres_data:/var/lib/postgresql/data/ # define where the postgres data will live within the postgres container
37    environment: # set environment variables from the .env file set using the env_file directive
39      - POSTGRES_DB=${DB_NAME}
40      - PGPORT=${DB_PORT}
42    restart: "on-failure" # restart db service if it fails
46  postgres_data: # setup storage volume for data held by the Postgres db
47  static_volume: # setup storage volume for static files such as css files and images.


The skills covered in this guide are vital for DevOps and full stack developer positions in any organization. The next level above multi-container single app management within the Docker ecosystem is multi-app or microservice management with technologies like Docker Swarm and Kubernetes.

These are referred to as container orchestration tools. They are used to manage the lifecycle and running of large apps designed as several individual containerized components referred to as microservices. To learn more about how container orchestration tools are used to manage microservice-based apps, follow this guide.