- Published at
Traefik and Flask with Docker Compose
A simple guide to setting up a Flask app with Traefik as a reverse proxy using Docker Compose. Learn how to configure routing and load balancing.
- Authors
-
-
- Name
- James Lau
- Indie App Developer at Self-employed
-
Table of Contents
- Traefik and Flask: A Simple Docker Compose Setup
- Project Structure
- Flask Application (flask-app)
- flask-app/app.py
- flask-app/requirements.txt
- flask-app/Dockerfile
- Traefik Configuration
- traefik/dynamic/dynamic.yml
- Docker Compose (docker-compose.yml)
- Running the Application
- Accessing the Application
- Explanation for Intermediate Learners
- Conclusion
Traefik and Flask: A Simple Docker Compose Setup
This post demonstrates how to set up a simple Flask application behind Traefik using Docker Compose. Traefik acts as a reverse proxy and load balancer, handling routing to your Flask app based on hostnames.
Project Structure
Here’s the directory structure we’ll be using:
.
├── docker-compose.yml
├── flask-app
│ ├── app.py
│ ├── Dockerfile
│ └── requirements.txt
└── traefik
└── dynamic
└── dynamic.yml
Flask Application (flask-app)
Let’s start with the Flask application. This is a basic “Hello, World!” app.
flask-app/app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello from Flask!'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
This code creates a Flask app that listens on port 5000 and returns “Hello from Flask!” when you visit the root path.
flask-app/requirements.txt
flask==2.3.2
This file specifies the Flask dependency for our application.
flask-app/Dockerfile
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
EXPOSE 5000
CMD ["python", "app.py"]
This Dockerfile sets up the Flask application environment. It:
- Uses a Python 3.9 slim base image.
- Sets the working directory to
/app. - Copies the
requirements.txtfile and installs the dependencies. - Copies the
app.pyfile. - Exposes port 5000.
- Runs the Flask application.
Traefik Configuration
Traefik is configured using a dynamic configuration file.
traefik/dynamic/dynamic.yml
http:
routers:
flask-router:
rule: "Host(`flask.localhost`)"
service: flask-service
entryPoints:
- web
services:
flask-service:
loadBalancer:
servers:
- url: "http://flask-app:5000"
This configuration defines:
- Router:
flask-routerthat listens for requests toflask.localhost. - Service:
flask-servicethat load balances requests to the Flask application athttp://flask-app:5000. - Entrypoint: Uses the
webentrypoint, which is configured to listen on port 80 (indocker-compose.yml).
Docker Compose (docker-compose.yml)
version: '3.8'
services:
traefik:
image: traefik:v3.4
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
- traefik-net
flask-app:
build: ./flask-app
labels:
- "traefik.enable=true"
- "traefik.http.routers.flask-router.rule=Host(`flask.localhost`)"
- "traefik.http.services.flask-service.loadbalancer.server.port=5000"
networks:
- traefik-net
whoami:
image: traefik/whoami
labels:
- "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"
networks:
- traefik-net
networks:
traefik-net:
driver: bridge
This docker-compose.yml file defines three services:
- traefik: The Traefik reverse proxy.
- It’s configured to use Docker as a provider, meaning it will automatically discover and configure routes based on Docker labels.
- It exposes ports 80 (for HTTP) and 8080 (for the Traefik dashboard).
- It mounts the Docker socket to allow Traefik to monitor Docker events.
- flask-app: The Flask application.
- It’s built from the
./flask-appdirectory using theDockerfile. - It uses labels to configure Traefik routing. These labels are an alternative to the
dynamic.ymlfile, defining the router, rule, and service directly within the Docker Compose file. Specifically, they define the same router as thedynamic.ymlfile, routingflask.localhostto the flask app. The labeltraefik.enable=trueis necessary for Traefik to consider the service. The port is defined for the service’s load balancer.
- It’s built from the
- whoami: A simple container that returns information about itself, used for testing Traefik routing. It routes
whoami.localhostto this container.
The traefik-net network allows the services to communicate with each other.
Running the Application
- Save all the files in the correct directory structure.
- Run
docker-compose up --buildin the root directory (wheredocker-compose.ymlis located).
Accessing the Application
- Add the following lines to your
/etc/hostsfile:
127.0.0.1 flask.localhost
127.0.0.1 whoami.localhost
- Open your browser and navigate to
http://flask.localhost. You should see “Hello from Flask!“. - Navigate to
http://whoami.localhost. You should see information about the whoami container. - You can access the Traefik dashboard at
http://localhost:8080(note that--api.insecure=trueis only for development and should NOT be used in production).
Explanation for Intermediate Learners
- Reverse Proxy: Traefik acts as a reverse proxy, sitting in front of your application and handling incoming requests. This allows you to do things like load balancing, SSL termination, and request routing.
- Load Balancing: Traefik can distribute traffic across multiple instances of your application, improving performance and availability.
- Docker Provider: Traefik’s Docker provider allows it to automatically discover and configure routes based on Docker labels. This makes it easy to manage routing for your Dockerized applications.
- Host Header: The
Hostheader is used to determine which application should handle a request. In this example, Traefik routes requests toflask.localhostto the Flask application. - Docker Networks: Docker networks allow containers to communicate with each other using their service names as hostnames.
Conclusion
This post demonstrated how to set up a simple Flask application behind Traefik using Docker Compose. This is a basic example, but it can be extended to more complex applications with multiple services and more sophisticated routing rules.