DEV Community

Cover image for Deploy The Multi-Container App
Arif Hossain
Arif Hossain

Posted on

Deploy The Multi-Container App

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.

Image description

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.

Image description

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
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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"]
Enter fullscreen mode Exit fullscreen mode

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:
Enter fullscreen mode Exit fullscreen mode

Image description

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
Enter fullscreen mode Exit fullscreen mode

Image description

Image description

Step 6: Verify the Deployment
Verify that the services are running:

docker compose ps
Enter fullscreen mode Exit fullscreen mode

You should see two services: web-fe and redis.

Expected output:

Image description

Check the logs for any errors:

docker compose logs
Enter fullscreen mode Exit fullscreen mode

Expected output:

Image description

Use the following command:

curl localhost:5001
Enter fullscreen mode Exit fullscreen mode

You should see the message indicating the number of visits to the page.

Expected output:

Image description

List the processes running inside of each service (container):

docker compose top
Enter fullscreen mode Exit fullscreen mode

Image description

Use the following command to stop the app without deleting its resources:

docker compose stop
Enter fullscreen mode Exit fullscreen mode

Image description

With the app in the stopped state, restart it with the docker compose restart command:

docker compose restart
Enter fullscreen mode Exit fullscreen mode

Image description

Verify the volume and network:
List volumes to verify counter-vol:

docker volume ls
Enter fullscreen mode Exit fullscreen mode

Image description

List networks to verify counter-net:

docker network ls
Enter fullscreen mode Exit fullscreen mode

Image description

Cleanup
When you're done testing, you can stop and remove the containers, networks, and volumes:

docker compose down --volumes
Enter fullscreen mode Exit fullscreen mode

Image description

###//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
Enter fullscreen mode Exit fullscreen mode

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)