A proper Flask deployment is more than just running python app.py. In this article, we will review a production setup with Docker Compose, Traefik as a reverse proxy, and automatic Let's Encrypt HTTPS certificates.
Why Traefik?
Traefik is a modern reverse proxy that can automatically discover Docker containers and issue SSL certificates for them via Let's Encrypt. This removes the need for manual Nginx and certbot configuration.
Project structure
A typical structure looks like this:
project/
├── app.py
├── Dockerfile
├── compose.yaml
└── .env
Dockerfile
Use the official Python image and gunicorn as the WSGI server:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:8000", "app:app"]
compose.yaml
In compose.yaml, define app and traefik services. Traefik needs access to the Docker socket to discover containers.
Important labels for the app container:
- traefik.enable=true
- traefik.http.routers.app.rule=Host(`your.domain.com`)
- traefik.http.routers.app.tls.certresolver=le
CI/CD with GitHub Actions
Automate deployment with GitHub Actions: on push to the main branch, the workflow connects to the server over SSH and runs docker compose pull && docker compose up -d.
Do not forget to add repository secrets: SSH key, server address, and domain.
Summary
The Flask + Gunicorn + Docker + Traefik stack provides a reliable production setup with minimal maintenance effort.