# Running a Flask Application Behind NGINX Using Docker Compose

`A hands-on guide to building a multi-container application using Flask, NGINX, and Docker Compose.`

## Introduction

Most production applications do not expose the application server directly to users. Instead, a reverse proxy such as NGINX sits in front of the application and handles incoming requests.

In this project, I built a simple architecture where:

*   NGINX receives client requests
    
*   NGINX forwards requests to a Flask application
    
*   Both services run as separate containers
    
*   Docker Compose manages the entire deployment
    

## Project Architecture

```plaintext
            User
              |
              v
        NGINX Proxy
          Port 80
              |
              v
       Flask Application
          Port 5000
```

The user only interacts with NGINX.

NGINX forwards traffic internally to the Flask container.

## Project Structure

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

## Step 1: Create the Flask Application

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

```plaintext
from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return """
    <h1>CloudOps Chronicle</h1>
    <h2>NGINX Reverse Proxy Demo</h2>
    """

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

The application listens on port **5000**.

## Step 2: Create requirements.txt

```plaintext
flask
```

This file contains the Python dependencies required by the application.

## Step 3: Create the 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"]
```

Build the image:

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

Verify:

```plaintext
docker images
```

## Step 4: Configure NGINX

Create `nginx.conf`:

```plaintext
events {}

http {

    server {

        listen 80;

        location / {

            proxy_pass http://web:5000;

        }

    }

}
```

The important part is:

proxy\_pass [http://web:5000](http://web:5000);

Here:

*   `web` is the Docker Compose service name
    
*   `5000` is the Flask application port
    

Docker Compose automatically provides DNS-based service discovery.

## Step 5: Create Docker Compose File

Create `docker-compose.yml`:

```plaintext
services:

  web:
    image: nginx-flask-web:latest
    container_name: flask-app-1

  nginx:
    image: nginx:latest
    container_name: nginx-proxy

    ports:
      - "80:80"

    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf

    depends_on:
      - web
```

## Step 6: Start the Application

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

Verify:

```plaintext
docker ps
```

Example output:

```plaintext
CONTAINER ID   IMAGE                 NAMES
xxxxxxxx       nginx:latest          nginx-proxy
xxxxxxxx       nginx-flask-web       flask-app
```

## Step 7: Test the Application

```plaintext
http://localhost
  or
http://<server-public-ip>
```

Although users access port 80, the application is actually running on port 5000.

NGINX handles the forwarding.

### Challenges Faced

During the implementation, you might encountered a few issues:

*   Docker Compose Buildx dependency requirements
    
*   Understanding the difference between `ports` and `expose`
    
*   Service discovery between containers
    
*   NGINX proxy configuration
    

### Conclusion

Running Flask behind NGINX using Docker Compose was an excellent exercise in understanding modern application architecture.

If you're learning Docker, I highly recommend trying this project before moving to Kubernetes.

Happy Learning!

for reference : https://github.com/h-manojbabu/docker-image-build/tree/main/nginx-flask
