Arif Hossain
Posted on November 9, 2024
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.
Posted on November 9, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 14, 2024