# Building a Multi-Container Flask and Redis Application Using Docker Compose



After building a static website container and a simple Flask application, I wanted to take the next step to running multiple containers together.

In real-world applications, a single container is rarely enough. Applications often need databases, caches, message queues, and supporting services.

In this project, I built a simple Flask application that communicates with a Redis container using Docker Compose.

By the end of this exercise, we can learned:

\-->Docker Compose  
\-->Multi-container applications  
\-->Container networking  
\-->Service discovery  
\-->Flask and Redis integration

Why Docker Compose?

Docker Compose allows us to define and run multiple containers as a single application.

Without Docker Compose:

`Container 1 → Start manually`

`Container 2 → Start manually`

`Network → Create manually`

`Dependencies → Configure manually`

With Docker Compose:

`docker compose up -d`

Everything starts automatically.

### Project Architecture

```plaintext
+-----------------+
| Flask Web App   |
| Port 5000       |
+--------+--------+
         |
         |
         v
+-----------------+
| Redis Database  |
| Port 6379       |
+-----------------+
```

The Flask application stores and retrieves a visitor counter from Redis.

### Project Structure

```plaintext
flask-redis/
├── app.py
├── requirements.txt
├── Dockerfile
├── docker-compose.yml
└── README.md
```

### Creating the Flask Application

Create a file named [`app.py`](http://app.py).

```plaintext
from flask import Flask
import redis

app = Flask(__name__)

redis_client = redis.Redis(host='redis', port=6379)

@app.route('/')
def index():
    try:
        visits = redis_client.incr('counter')
        return f"""
        <h1>CloudOps Chronicle</h1>
        <h2>Docker Compose Demo</h2>
        <h3>Visits: {visits}</h3>
        """
    except Exception as e:
        return f"Error: {e}"

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)
```

The application increments a counter every time the page is refreshed.

### Defining Dependencies

Create `requirements.txt`.

```plaintext
flask
redis
```

These packages are installed when the Docker image is built.

### Creating the Dockerfile

Create `Dockerfile`.

```plaintext
FROM python:3.12-slim

WORKDIR /app

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

COPY app.py .

EXPOSE 5000

CMD ["python", "app.py"]
```

### Creating Docker Compose Configuration

Create `docker-compose.yml`.

```plaintext
services:

  web:
    image: flask-redis-web:latest
    container_name: flask-web

    ports:
      - "5000:5000"

    depends_on:
      - redis

  redis:
    image: redis:latest
    container_name: redis-server
```

This file defines: Flask container, Redis container, Container Dependencies, Port mapping.

### Building the Application Image

Build the Flask container image.

```plaintext
docker build -t flask-redis-web .
```

Verify:

```plaintext
docker images
```

Example:

```plaintext
REPOSITORY         TAG
flask-redis-web    latest
redis              latest
```

### Starting the Application

Launch both containers together.

```plaintext
docker compose up -d
```

Verify:

```plaintext
docker ps
```

Output:

```plaintext
CONTAINER ID   IMAGE                    NAMES
265e8b0b5xxx   flask-redis-web:latest   flask-web
fdbf76392xxx   redis:latest             redis-server
```

Both services are now running successfully.

### Testing the Application

Access:

```plaintext
http://<server-ip>:5000
```

### Checking Container Logs

```plaintext
docker logs flask-web
docker logs redis-server
docker compose logs
```

These commands are useful when troubleshooting containerised applications.

### Challenges Faced

`During the implementation, I encountered a few issues:`

*   `Docker Compose plugin compatibility`
    
*   `Buildx requirements`
    
*   `Git push conflicts caused by remote repository changes`
    
*   `Container dependency configuration`
    

### Happy Learning!
