A simple Python web application with an nginx reverse proxy, deployed in Docker containers using Docker Compose.
.
├── .github/
│ └── workflows/
│ └── ci.yml
├── backend/
│ ├── Dockerfile
│ └── app.py
├── nginx/
│ └── nginx.conf
├── docker-compose.yml
└── README.md
User
│
▼
http://localhost:80 (host port)
│
nginx (container devops-example-nginx)
│
▼ proxy_pass → http://backend:8080
backend (container devops-example-backend)
- backend — a Python HTTP server (
http.server), listens on port8080, reachable only inside the Docker network. - nginx — the official nginx image, accepts HTTP requests on port
80and proxies them to the backend. - The services communicate over the internal Docker network
devops-example-networkvia service names.
-
Clone the repository:
git clone <repository-url> cd <repository-name>
-
Build and start the containers:
docker compose up -d --build
-
Make sure the containers are running:
docker compose ps
Send a request to nginx:
curl http://localhostExpected response:
Hello from DevOps Example!
docker compose downIf you also need to remove the built images:
docker compose down --rmi local- Python 3.12 (official
python:3.12-alpineimage) - nginx 1.27 (official
nginx:1.27-alpineimage) - Docker / Docker Compose
- GitHub Actions (CI)
On every push to main and on every pull request, a pipeline
(.github/workflows/ci.yml) runs that:
- Builds the Docker images (
docker compose build). - Brings up the whole stack (
docker compose up -d). - Runs a smoke test: a request through nginx must return
Hello from DevOps Example!. - Verifies that the backend is not reachable from the host directly (only through nginx).