This project sets up a reverse proxy architecture using Docker Compose with Nginx acting as a reverse proxy to two backend services:
- Service 1 (Go HTTP server)
- Service 2 (Python Flask API using
uv)
The system exposes both services on a single port (localhost:8080) with path-based routing, centralized logging, and health checks.
.
├── docker-compose.yaml
├── test.sh
├── nginx/
│ ├── Dockerfile
│ └── default.conf
├── service_1/
│ ├── Dockerfile
│ └── main.go
├── service_2/
│ ├── .venv/
│ ├── .dockerignore
│ ├── .python-version
│ ├── Dockerfile
│ ├── app.py
│ ├── pyproject.toml
│ └── uv.lock
-
Prerequisites
Ensure you have the following installed:- Docker
- Docker Compose
-
Clone the Repository
git clone https://github.com/Janeesh23/Nginx_and_Docker_compose.git cd Nginx_and_Docker_compose/ -
Build & Start the System
From the root directory:
docker-compose up --build
-
Test the Services
You can run the provided script to test routing and health:
chmod +x test.sh ./test.sh
Nginx is configured to handle path-based routing. Requests to specific paths are forwarded to different backend services:
| Route Prefix | Routed To | Port | Description |
|---|---|---|---|
/service1/ping |
Go service | 8001 |
Health check for Service 1 |
/service1/hello |
Go service | 8001 |
Greeting from Service 1 |
/service2/ping |
Python Flask app | 8002 |
Health check for Service 2 |
/service2/hello |
Python Flask app | 8002 |
Greeting from Service 2 |
All routes are accessed via the Nginx container through:
http://localhost:8080
Example:
- http://localhost:8080/service1/hello → forwards to Service 1
- http://localhost:8080/service2/ping → forwards to Service 2
- Both services expose a
/pingendpoint that returns:{ "status": "ok", "service": "<id>" } - Used by:
- Docker healthcheck
test.shautomation script
- Nginx logs include timestamp, client IP, request path, and status code in a clean, custom format:
23/Jun/2025:16:54:15 +0000 | 172.18.0.1 | /service2/hello | 200
test.shperforms:- Route checks (
pingandhellofor both services) - Displays matching Nginx log entries
- Fails gracefully if any route is unreachable
- Route checks (
- Go app uses multi-stage build
- Python Flask app uses
uvrunner in a minimal base image