Deploy the multi-container application using Docker Compose
In this session, we will learn how to define services, networks, and volumes in a Docker Compose file and verify the setup by running a simple application.
We'll need to set up the directory structure, create the necessary files (app.py, Dockerfile, compose.yaml), and then deploy and verify the application.
Here's a step-by-step guide:
Step 1: Set Up Directory Structure
Create a directory for your project:
mkdir multi-container
cd multi-container
Step 2: Create app.py
Inside the multi-container directory, create a file named app.py:
from flask import Flask
from redis import Redis
app = Flask(__name__)
redis = Redis(host='redis', port=6379)
@app.route('/')
def hello():
count = redis.incr('hits')
return f'Hello World! This page has been visited {count} times.\n'
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080)
The app.py script creates a simple web application using Flask. When accessed, it counts the number of visits to the root URL and displays a message with the visit count. This count is stored in a Redis database. The script runs a web server to serve the application on port 8080.
Step 3: Create Dockerfile
Create a Dockerfile in the same directory:
# Use the official Python image from the Docker Hub
FROM python:3.9-alpine
# Set the working directory in the container
WORKDIR /app
# Copy the current directory contents into the container at /app
COPY . /app
# Install any needed packages specified in requirements.txt
RUN pip install flask redis
# Make port 8080 available to the world outside this container
EXPOSE 8080
# Define environment variable
ENV NAME World
# Run app.py when the container launches
CMD ["python", "app.py"]
The Dockerfile builds a Docker image for the web-fe service in the Docker Compose setup. It uses the official Python 3.9 Alpine image, sets the working directory to /app, copies the current directory's contents into the container, installs Flask and Redis, exposes port 8080, and runs the Flask application (app.py) when the container starts. This setup ensures the web-fe service is ready to serve the application and interact with the Redis service defined in the compose.yaml file.
Step 4: Create compose.yaml
Create a compose.yaml file:
version: '3.8'
services:
web-fe:
build: .
command: python app.py
ports:
- target: 8080
published: 5001
networks:
- counter-net
volumes:
- type: volume
source: counter-vol
target: /app
redis:
image: "redis:alpine"
networks:
- counter-net
networks:
counter-net:
volumes:
counter-vol:
The compose.yaml file defines a multi-container application using Docker Compose. It consists of two services:
web-fe:
Builds an image using the current directory's Dockerfile.
Runs a Python script (app.py) to serve a Flask application.
Maps port 5001 on the host to port 8080 in the container.
Connects to the counter-net network.
Mounts a volume named counter-vol to the /app directory in the container.
redis:
Pulls the redis:alpine image from Docker Hub.
Connects to the counter-net network.
The counter-net network facilitates communication between the web-fe and redis services. Additionally, the counter-vol volume provides persistent storage for the web-fe service.
It’s also worth knowing that Compose builds networks and volumes before deploying services. This makes sense, as networks and volumes are lower-level infrastructure objects that are consumed by services (containers).
Step 5: Deploy the Application
With all the files in place, you can now deploy the application using Docker Compose. Run the following command from the multi-container directory:
docker compose -f compose.yaml up -d
Step 6: Verify the Deployment
Verify that the services are running:
docker compose ps
You should see two services: web-fe and redis.
Expected output:
Check the logs for any errors:
docker compose logs
Expected output:
Use the following command:
curl localhost:5001
You should see the message indicating the number of visits to the page.
Expected output:
List the processes running inside of each service (container):
docker compose top
Use the following command to stop the app without deleting its resources:
docker compose stop
With the app in the stopped state, restart it with the docker compose restart command:
docker compose restart
Verify the volume and network:
List volumes to verify counter-vol:
docker volume ls
List networks to verify counter-net:
docker network ls
Cleanup
When you're done testing, you can stop and remove the containers, networks, and volumes:
docker compose down --volumes
###//Understand another Example//###
Let's investigate docker-compose.yml to understand.
version: '3.5'
services:
api:
build: .
volumes:
- "./app:/src/app"
ports:
- "1338:1338"
depends_on:
- db
- cache
networks:
- test_nw
environment:
- DATABASE_HOST=mongodb://db:27017
- REDIS_CACHE_HOST=redis://cache:6379
- PORT=1338
db:
image: mongo:latest
ports:
- "27017:27017"
networks:
- test_nw
cache:
image: redis:latest
ports:
- "6379:6379"
networks:
- test_nw
networks:
test_nw:
driver: bridge
This is a simple docker-compse.yml example to deploy a Nodejs backend with MongoDb and Redis.
The Commands
Of course docker-compose has commands. Whaat! Okay I' will give you the most basic commands. I'm not super duper software engineer and I can live my life with these commands.
docker compose up
is a command that will look for docker-compose.yml by default and will process the docker-compose.yml, create the environment and run the services.
-d
means that terminal is yours, it runs the command detachable mode
-f
#non-standard-compose.yml-name# means that you can pass a compose.yml file with different name. Usaually projects contains more than one docker-compose files. You can have compose file for production and development or you can seperate applications and tools in a different compose files.
docker compose down
is a command that will look for running compose.yml file and shutdown containers then remove all of them including networks, volumes etc.
docker compose log
is a command that will look for running compose.yml file and displays log which are generated by the containers.
Top Level Definitions
version : Defined by the Compose Specification for backward compatibility. It is only informative, and you'll receive a warning message that it is obsolete if used.
services : A service is an abstract definition of a computing resource within an application which can be scaled or replaced independently from other components. These services run in their containers and can communicate with each other.
network : A layer that allows containers to communicate with each other.
volume: Volumes are persistent data stores implemented by the container engine. Compose offers a neutral way for services to mount volumes, and configuration parameters to allocate them to infrastructure.
Service Definitions
build: Lets you define the Dockerfile path to build when the compose file is being processed.
volumes : Lets you define service-level persisted volumes to mount local files and folders.
ports: Lets you expose container ports. The left-hand of the definition is the localhost address and the right-hand will be the container port. It basically means binding port 1338 of the container to localhost:1338.
depends_on : option in Docker Compose is used to specify the dependencies between different services defined in your docker-compose.yml file.
networks: option in Docker Compose is used to specify which network will be used by this container.
environment: option in Docker Compose is used to specify environment variables which will be passed to container.
This setup allows you to run and verify the multi-container Flask application using Docker Compose, with persistent storage and network configuration as described.
Top comments (0)