Compose makes it easier to scale and deploy applications in Docker by automating container management. In this tutorial, we will take a detailed look at how to set up and use Docker Compose in your own production environment.
What is Docker Compose?¶
Docker Compose is used to manage applications and increases the efficiency of container development. Configurations are defined in a single YAML file to make it easier to build and scale applications. While Docker Compose is often used to set up a local environment, it can also be part of a continuous integration/continuous delivery (CI/CD) workflow. Developers can define a specific version of containers for testing or for a particular phase of the pipeline. Enough to facilitate the identification of problems and the correction of bugs before moving into production itself.
Docker Compose: prerequisites¶
For the orchestration of containers, you need both Docker Engine and Docker Compose. You must therefore have one of the following two configurations:
- either Docker Engine and Docker Compose installed as standalone binaries;
- either Docker Desktop in development environment with graphical user interface, which already includes Docker Engine and Compose.
To learn how to install Docker Compose on other operating systems, check out our dedicated tutorials:
Use Docker Compose step by step¶
We will now explain the concepts of Docker Compose with a simple Python web application whose calls will be counted. To do this, we will use the Python Flask framework and the Redis in-memory database. There is no need to install Python or Redis, as they are provided as Docker images.
Step 1: Create the project files¶
Open the terminal and create a new folder for the project.
Then go to the directory.
In this folder, create the file app.py and add the following code:
import time
import redis
from flask import Flask
app = Flask(__name__)
cache = redis.Redis(host=‘redis’, port=6379)
def get_hit_count():
retries = 5
while True:
try:
return cache.incr(‘hits’)
except redis.exceptions.ConnectionError as exc:
if retries == 0:
raise exc
retries -= 1
time.sleep(0.5)
@app.route(‘/’)
def hello():
count = get_hit_count()
return ‘Hello World! I was here {} times.\n’.format(count)
python
We will use the hostname “Redis” and the standard port “6379”. Furthermore, we indicate that the function get_hit_count()
will have to make several attempts to connect to the service. We suggest this process because Redis may not yet be available when the application starts or there may be connection issues while running.
Finally create the file requirements.txt with dependencies:
Step 2: configure the dockerfile¶
THE dockerfile is used for Docker image. It shows all the dependencies that the Python application needs.
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"]
shell
Docker is thus instructed to use the Python 3.7 image. Additionally, we set the environment variables for the command Flask. With apk add
we install gcc and other dependencies. EXPOSE
indicates that the container should monitor port 5000. With COPY
the contents of the current folder are copied to the working directory /coded. As standard order for container, we choose flask run
.
Verify that the dockerfile was saved without a file extension, as some editors automatically add the suffix .txt.
Step 3: Create the YAML file¶
In docker-compose.ymlwe configure the “redis” and “web” services.
version: "3.9"
services:
web:
build: .
ports:
- "8000:5000"
redis:
image: "redis:alpine"
yaml
The web service uses the image created by the dockerfile. It associates the container and the host computer with port 8000, while the web server Flask works on port 5000. In contrast, the Redis image is simply obtained from the official Docker hub.
Step 4: Run the app with Compose¶
Start the application from your project folder.
Call http://localhost:8000 in your browser. You can also enter http://127.0.0.1:8000.
You should see the following message displayed:
Refresh the page. The view count should now have increased by 1.
You can stop the application with:
$ docker compose down
shell
You can also press Ctrl
+ C
in the terminal in which you launched the application.
Step 5: Add a Bind Mount¶
If you want to add a Bind Mount (or directory mapping) for web service you can do this in docker-compose.yml.
version: "3.9"
services:
web:
build: .
ports:
- "8000:5000"
volumes:
- .:/code
environment:
FLASK_DEBUG: "true"
redis:
image: "redis:alpine"
yaml
Below Volumeswe indicate that the current project folder must be attached to the directory /coded inside the container. This allows you to modify the code without having to recreate the image. The environment variable FLASK_DEBUG
orders to flask run
to run in development mode.
Step 6: Recreate and Run the Application¶
Enter the following command in the terminal to reset the Compose file:
Step 7: Update the app¶
Since you are now using a directory mapping for your application, you can modify your code and automatically see the changes without having to recreate the image.
Write a new welcome text in app.py.
return ‘Hello from Docker! I was here {} times.\n’.format(count)
python
Refresh your browser to see if the changes have been taken into account.
Step 8: Additional Commands¶
The option --help
displays a list of commands available for Docker Compose:
docker compose --help
shell
To let Docker Compose run in the background, add the argument -d
:
docker compose up -d
shell
With down
, all containers are deleted. The option --volumes
also deletes volumes used by the Redis container.
docker compose down --volumes
shell