Traefik
La configuration d'un reverse proxy traditionnel exige une intervention manuelle à chaque ajout ou modification d'un service : éditer un fichier de configuration, tester la syntaxe, recharger le process. Dans un environnement conteneurisé où les services démarrent et s'arrêtent fréquemment, cette approche ne tient pas. Traefik r ésout ce problème en découvrant automatiquement les services depuis Docker ou Kubernetes et en générant sa configuration à la volée, sans interruption de service.
Modèle mental
Traefik sépare clairement la configuration statique (démarrée une fois au lancement) de la configuration dynamique (mise à jour en temps réel depuis les providers).
Configuration statique : entrypoints (ports d'écoute), providers (sources de config), certificate resolvers (ACME). Ne peut pas être rechargée à chaud.
Configuration dynamique : routers, services, middlewares. Rechargée à chaud depuis les labels Docker, les annotations Kubernetes, ou des fichiers de config.
Configuration statique (flags CLI / traefik.yml)
└── Entrypoints (ports 80, 443)
└── Providers (Docker, Kubernetes, File)
└── Certificate resolvers (Let's Encrypt)
Configuration dynamique (labels, annotations, fichiers)
└── Routers (règles de matching)
└── Middlewares (transformations)
└── Services (backends)
Un router fait le matching entre une requête entrante et un service. Une règle de router combine des prédicats : Host(\api.example.com`), PathPrefix(`/api`), Method(`GET`), Headers(`X-Api-Key`, `.*`)`.
Déploiement avec Docker
Traefik lit les labels Docker en montant le socket Docker en lecture seule.
services:
traefik:
image: traefik:v3.0
command:
- --api.dashboard=true
- --api.insecure=false
- --providers.docker=true
- --providers.docker.exposedByDefault=false # sécurité : opt-in par service
- --providers.docker.network=proxy # réseau Docker par défaut pour les backends
- --entrypoints.web.address=:80
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.web.http.redirections.entrypoint.scheme=https
- --entrypoints.websecure.address=:443
- --certificatesresolvers.letsencrypt.acme.email=admin@example.com
- --certificatesresolvers.letsencrypt.acme.storage=/acme.json
- --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./acme.json:/acme.json
networks:
- proxy
networks:
proxy:
external: true
touch acme.json && chmod 600 acme.json
docker network create proxy
docker compose up -d
Un service s'expose avec quelques labels :
services:
api:
image: myapp:latest
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`api.example.com`)"
- "traefik.http.routers.api.entrypoints=websecure"
- "traefik.http.routers.api.tls.certresolver=letsencrypt"
- "traefik.http.services.api.loadbalancer.server.port=8000"
Traefik détecte le conteneur au démarrage et configure immédiatement le router — sans redémarrer Traefik.
Middlewares
Les middlewares transforment les requêtes entre le router et le backend. Ils se définissent séparément et s'attachent à un ou plusieurs routers.
Redirection HTTPS (déjà faite au niveau de l'entrypoint ci-dessus, mais faisable par middleware aussi) :
labels:
- "traefik.http.middlewares.redirect-https.redirectscheme.scheme=https"
- "traefik.http.middlewares.redirect-https.redirectscheme.permanent=true"
- "traefik.http.routers.api-http.middlewares=redirect-https"
BasicAuth :
# Générer le hash du mot de passe
htpasswd -nb admin secretpassword
# Résultat : admin:$apr1$...
labels:
- "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$..." # doubler les $
- "traefik.http.routers.dashboard.middlewares=auth"
Rate limiting :
labels:
- "traefik.http.middlewares.ratelimit.ratelimit.average=100" # requêtes/s moyennes
- "traefik.http.middlewares.ratelimit.ratelimit.burst=50" # pic autorisé
- "traefik.http.routers.api.middlewares=ratelimit"
Modification de headers :
labels:
- "traefik.http.middlewares.secheaders.headers.forceSTSHeader=true"
- "traefik.http.middlewares.secheaders.headers.stsSeconds=63072000"
- "traefik.http.middlewares.secheaders.headers.contentTypeNosniff=true"
- "traefik.http.middlewares.secheaders.headers.frameDeny=true"
- "traefik.http.routers.api.middlewares=secheaders"
Chaîner plusieurs middlewares :
labels:
- "traefik.http.routers.api.middlewares=auth,ratelimit,secheaders"
L'ordre des middlewares dans la chaîne est alphabétique par défaut — pour contrôler l'ordre, utiliser des fichiers de configuration dynamique.
Routing TCP
Traefik peut aussi proxifier du trafic TCP (base de données, MQTT, etc.) via le provider Docker.
services:
postgres:
image: postgres:16
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.tcp.routers.postgres.rule=HostSNI(`*`)" # sans TLS : accepter tout
- "traefik.tcp.routers.postgres.entrypoints=postgres"
- "traefik.tcp.services.postgres.loadbalancer.server.port=5432"
# Dans la configuration statique Traefik
command:
- --entrypoints.postgres.address=:5432
Pour le routing TCP avec TLS, HostSNI peut filtrer sur le nom du serveur (SNI) — permet de router plusieurs services TLS sur le même port.
Déploiement Kubernetes (IngressRoute)
En Kubernetes, Traefik expose une CRD IngressRoute plus expressive que l'API Ingress standard :
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: api-route
namespace: default
spec:
entryPoints:
- websecure
routes:
- match: Host(`api.example.com`) && PathPrefix(`/v2`)
kind: Rule
middlewares:
- name: ratelimit
services:
- name: api-service
port: 8000
tls:
certResolver: letsencrypt
# Installation via Helm
helm repo add traefik https://traefik.github.io/charts
helm install traefik traefik/traefik \
--set ingressRoute.dashboard.enabled=false \
--set ports.web.redirectTo.port=websecure
Certificate Resolvers
Traefik supporte deux challenges ACME pour Let's Encrypt :
HTTP-01 : Let's Encrypt contacte le serveur sur le port 80 pour vérifier la possession du domaine. Le domaine doit résoudre vers l'IP publique de la machine. Ne supporte pas les wildcards.
DNS-01 : Traefik crée un enregistrement TXT dans la zone DNS du domaine pour prouver la possession. Fonctionne derrière un NAT, pour des machines non exposées publiquement, et supporte les wildcard (*.example.com). Nécessite une intégration avec le provider DNS (Route53, Cloudflare, OVH, etc.).
command:
- --certificatesresolvers.cloudflare.acme.dnschallenge=true
- --certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare
- --certificatesresolvers.cloudflare.acme.email=admin@example.com
- --certificatesresolvers.cloudflare.acme.storage=/acme.json
environment:
CF_API_EMAIL: admin@example.com
CF_API_KEY: your_cloudflare_api_key
Dashboard et observabilité
Le dashboard Traefik (port 8080 par défaut) liste les routers, middlewares, services et l'état des certificats TLS. En production, le protéger impérativement :
labels:
- "traefik.enable=true"
- "traefik.http.routers.dashboard.rule=Host(`traefik.example.com`)"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.middlewares=auth"
- "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$..."
Traefik expose des métriques Prometheus sur /metrics — compatibles avec Grafana pour visualiser le trafic, la latence et les erreurs par router.
command:
- --metrics.prometheus=true
- --metrics.prometheus.buckets=0.1,0.3,1.0,2.5
- --accesslog=true
- --accesslog.format=json
Les logs d'accès en JSON simplifient l'ingestion dans des stacks de centralisation (Loki, Elasticsearch).