Docker Compose: A hassle-free way to optimize multi-container deployments

To define and run multi-container Docker applications with the help of services define in the YAML file and start them with a single command and improve your productivity.

An application can have multiple containers running different services. which could have both frontend and backend services. It may be annoying and time-consuming to manage containers manually with docker. To overcome this, docker created a tool called docker-compose to handle multiple containers at once.

Figure 1: docker-compose overview
Figure 1: docker-compose overview

What is Docker Compose?

Docker Compose is a software used for defining and running multi-container docker applications. It can handle multiple containers at the same time in different environments.

Workflow for Docker Compose

  • Create a Dockerfile to build a custom image. (one may use an existing image)
  • Create a docker-compose.yaml file to define the services.
  • To start and run applications, use the docker-compose upcommand.

The YAML file specifies the application’s services with rules which define how it should be run. 

docker-compose.yaml is a default configuration file name. One can give any name but need to pass -f <file_name.yaml> as a configuration file to start the services defined in that file.

Advantages and Disadvantages

There are several advantages and disadvantages of docker-compose which are as follows

Advantages

  • Configuration: With the YAML file and environment variables, one can easily construct or modify application services quickly.
  • Security: All the containers are isolated from each other though they are created with a single command.
  • Productivity: It reduces the time to perform the task.
  • Portability: Developers can access and share files easily as everything is defined in a single YAML file.
  • Resources: One can run everything on the same hardware by creating a different directory for different projects, which saves resources. 
  • Re-usability: Containers are not created again if it is not changed, which may result in resource efficiency and speed.

Disadvantages

  • Failure Recovery: Works like an orchestrator but won’t recreate failed containers. The server may have a single-point failure.
  • Rolling update: No, rolling updates are supported. It can not replace containers without downtime. 
  • Do Not Support System Reboot: It can not work with a reboot. Changes in YAML files can not be recovered. It is erased from the docker memory once the system gets down.

Docker-compose is designed to run multiple containers on a single host while Kubernetes provides container orchestration for multiple cloud environments and clusters and also overcomes the disadvantages of docker-compose. 

Characteristics of Docker Compose

  • Multiple Isolated Environments on the Same Host

Compose keeps environments isolated for different projects on a single host using project names or directory names. By default, the project name is the name of the project directory in which the docker-compose.yaml file is located. 

  • Add Environment Variables

By adding an environment variable in the yaml file, One can modify the containers for different environments or users. The environment variable can be set in the shell or in the .env file. By default, compose uses the value from the .env file, but the value set in the shell will override the value of the .env file.

  • Retain Volumes When Containers are created

It saves data used by the services defined in docker-compose.yaml file. Data created in containers will not be lost. When it runs, docker-compose will find the container from previous runs, if available, and copy their volumes.

  • Re-Use Containers From Previous Run

If there is no change it uses the container created with the previous run so users can achieve the services faster.

  • Extend a Compose file

It is used to share the common configuration file among different files or in different projects. It never extends depends_on and volume_from properties as it is specific to local. Refer more about extends here.

Commands of Docker Compose

Installation

There are two ways to install docker-compose:

In this hands-on lab, we will be using the docker-compose standalone version.

  • First, install docker as a prerequisite on this Ubuntu Linux distribution.
apt update && apt install docker.io -y
  • Download Docker Compose standalone binary for ubuntu linux distribution
curl -L "https://github.com/docker/compose/releases/download/v2.17.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
  • Set the executable permission.
chmod +x /usr/local/bin/docker-compose
  • Check the version of docker-compose
docker-compose version

Creating a Python App and Spinning up with Docker Compose

This application uses the Flask framework and maintains a hit counter in Redis.

mkdir /root/python_app && cd /root/python_app
vim app.py
  • Create app.py in the project directory
import time
import redis
from flask import Flask
python_app = Flask(__name__)   #custom name of flask app
store = redis.Redis(host='redis', port=6379) #default port redis
def number_of_strike():  #function to get hits
    while True:
              return store.incr('hits')
@python_app.route('/') 
def message():    #function to display message
    return "Welcome to my Web Page.\nThis Web Application strike for {} times.\n".format(number_of_strike())
  • Create another file called requirements.txt in the same directory. 
vim requirements.txt
flask 
redis
  • Create a file named Dockerfile.
vim Dockerfile
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]
  • Create a file called docker-compose.yaml in the project directory where web and redis are two services in it.

In the web service, we will build the docker image from the Dockerfile we created above and map the host port 8000 to container port 5000

vim docker-compose.yaml
version: "3.9"
services:
  web:
    build: .
    ports:
      - "8000:5000"
  redis:
    image: "redis:alpine"
  • To start the application in the foreground.
docker-compose up

To detach from running applications as it occupies the terminal. Press Ctrl + C

NOTE: One can start only one service also with docker-compose up [services]

  • Do some changes in app.py  again build the customized image with
docker-compose build
  • To start the application in the background use -d flag
docker-compose up -d

  Click on app-8000 to see the Application.

Figure 2: Python web page
Figure 2: Python web page
  • To list the containers created by the application described in docker-compose.yaml
docker-compose ps
  • To stop all the containers created by the application described in docker-compose.yaml
docker-compose stop
  • To remove the containers for the given application, defined in docker-compose.yaml
docker-compose down

To remove the application containers completely with their volumes, use docker-compose down -v

  • List out the running compose projects
docker-compose ls
  • By default, Docker Compose uses the directory name as the project name. To provide a custom project name use,
docker-compose --project-name my_python_app up  

Using Docker Compose to Start Application with Docker Images

RSVP is derived from the French phrase Répondez s’il vous plaît, means “Please respond”, to require confirmation of an invitation. This Applicaion will provide total responds for host to organize well.

  • Create a folder to isolate the project environment.
mkdir /root/demo_rsvp && cd /root/demo_rsvp 
  • Create a rsvp_app.yaml compose file in the folder. Networks, Volumes, and Extends are used in this yaml file.
vim rsvp_app.yaml
version: '3.3'
services:
   db:
     image: mongo:3.6
     volumes:
       - db_data:/data/db
     restart: always
     expose:
       - "27017"
   
   webapp:
     depends_on:
       - db
     image: teamcloudyuga/rsvpapp
     ports:
       - "8000:5000"
     restart: always
     extends:
       file: common.yaml
       service: app
volumes:
    db_data: {}
  • Create extended file common.yaml in the same folder. 
vim common.yaml 
services:
  app:
    environment:
      MONGODB_HOST: db
      LINK: http://www.meetup.com/cloudyuga/
      TEXT1: CloudYuga 
      TEXT2: Garage RSVP!
      LOGO: https://raw.githubusercontent.com/cloudyuga/rsvpapp/master/static/cloudyuga.png
      COMPANY: CloudYuga Technology Pvt. Ltd.
  • To start the application in the foreground. 
docker-compose -p rsvp -f rsvp_app.yaml up

Press Ctrl + c to stop it.

Figure 3: Terminal Output of RSVP application
Figure 3: Terminal Output of RSVP application
  • To start the application in the background. 
docker-compose -p rsvp -f rsvp_app.yaml up -d

Click on app-8000 to see the Application.

Figure 4: RSVP application
Figure 4: RSVP application
Figure 5: RSVP Count on inserting data
Figure 5: RSVP Count on inserting data

Summary

Docker Compose is a tool to quickly deploy and scrap containers. The compose file can run seamlessly on any machine installed with docker-compose. I hope this blog helped in the understanding of Docker Compose. I’d love to hear comments from more people for betterment.

Join Our Newsletter

Share this article:

Table of Contents