Docker Compose helps you manage multiple containers in a declarative way. You can create a YAML file and specify what you want to build, what containers you want to run, and how the containers interact with each other. You can define mounts, networks, port mapping, and many different configurations in the YAML file.
After that, you can simply run docker compose up to run your entire containerized application.
Declarative management is quickly gaining ground because of its power and simplicity. Now, sysadmins don’t need to remember what commands they had run or write lengthy scripts or playbooks to manage containers. Instead, they can simply declare what they want in a YAML file, and docker compose or other tools can help them achieve that state. We installed Docker Compose when we installed Docker, so let’s see it in action with a sample application.
Deploying a sample application with Docker Compose
We have a Python Flask application that listens on port 5000, which we will eventually map to host port 80. The application will connect to the Redis database as a backend service on its default port, 6379, and fetch the page’s last visit time. We will not expose that port to the host system. This means the database is entirely out of bounds for any external party with access to the application.
The following diagram depicts the application architecture:
Figure 3.5 – Sample application
The necessary files are available in this book’s GitHub repository. Run the following command to locate the files:
$ git clone https://github.com/PacktPublishing/Modern-DevOps-Practices-2e.git \ modern-devops
$ cd modern-devops/ch3/docker-compose
$ ls -l
total 16
-rw-r–r– 1 root root 681 Nov 25 06:11 app.py
-rw-r–r– 1 root root 389 Nov 25 06:45 docker-compose.yaml
-rw-r–r– 1 root root 238 Nov 25 05:27 Dockerfile
-rw-r–r– 1 root root 12 Nov 25 05:26 requirements.txt
The app.py file looks as follows:
import time
import redis
from flask import Flask
from datetime import datetime
app = Flask(__name__)
cache = redis.Redis(host=’redis’, port=6379)
def get_last_visited():
try:
last_visited = cache.getset(‘last_visited’,str(datetime.now().strftime(“%Y-%m-%d, %H:%M:%S”)))
if last_visited is None:
return cache.getset(‘last_visited’,str(datetime.now().strftime(“%Y-%m-%d,
%H:%M:%S”)))
return last_visited
except redis.exceptions.ConnectionError as e:
raise e
@app.route(‘/’)
def index():
last_visited = str(get_last_visited().decode(‘utf-8’))
return ‘Hi there! This page was last visited on {}.\n’.format(last_visited)
The requirements.txt file looks as follows:
flask
redis
I’ve already built the application for you, and the image is available on Docker Hub. The next chapter will cover how to build a Docker image in detail. For now, let’s have a look at the docker-compose file.