🚦 Traefik
Reverse proxy moderne et dynamique, parfait pour les environnements Docker.
Traefik détecte automatiquement les services Docker et configure le routage via les labels.
Installation avec Docker Compose
Configuration de base
version: '3.8'
services:
traefik:
image: traefik:v3.0
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/traefik.yml:ro
- ./acme.json:/acme.json
- ./config:/config:ro
networks:
- proxy
networks:
proxy:
external: trueFichier traefik.yml
api:
dashboard: true
insecure: true # À désactiver en production
entryPoints:
http:
address: ":80"
http:
redirections:
entryPoint:
to: https
scheme: https
https:
address: ":443"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
network: proxy
file:
directory: /config
watch: true
certificatesResolvers:
letsencrypt:
acme:
email: ton@email.com
storage: acme.json
httpChallenge:
entryPoint: httpLabels Docker
Service basique
services:
app:
image: mon-app
labels:
- "traefik.enable=true"
- "traefik.http.routers.app.rule=Host(`app.example.com`)"
- "traefik.http.routers.app.entrypoints=https"
- "traefik.http.routers.app.tls.certresolver=letsencrypt"
- "traefik.http.services.app.loadbalancer.server.port=3000"
networks:
- proxyRègles de routage
# Par domaine
- "traefik.http.routers.app.rule=Host(`app.example.com`)"
# Par chemin
- "traefik.http.routers.app.rule=PathPrefix(`/api`)"
# Combiné
- "traefik.http.routers.app.rule=Host(`example.com`) && PathPrefix(`/api`)"
# Plusieurs domaines
- "traefik.http.routers.app.rule=Host(`app.example.com`) || Host(`www.app.example.com`)"
# Avec regex sur le path
- "traefik.http.routers.app.rule=Host(`example.com`) && PathPrefix(`/api/{version:v[0-9]+}`)"Middlewares
Redirection HTTP vers HTTPS
labels:
- "traefik.http.middlewares.redirect-https.redirectscheme.scheme=https"
- "traefik.http.middlewares.redirect-https.redirectscheme.permanent=true"
- "traefik.http.routers.app-http.middlewares=redirect-https"Basic Auth
labels:
# Générer le hash: echo $(htpasswd -nb user password) | sed -e s/\\$/\\$\\$/g
- "traefik.http.middlewares.auth.basicauth.users=user:$$apr1$$..."
- "traefik.http.routers.app.middlewares=auth"N’oublie pas de doubler les $ dans les fichiers Docker Compose pour échapper le caractère.
Headers de sécurité
labels:
- "traefik.http.middlewares.security-headers.headers.frameDeny=true"
- "traefik.http.middlewares.security-headers.headers.contentTypeNosniff=true"
- "traefik.http.middlewares.security-headers.headers.browserXssFilter=true"
- "traefik.http.middlewares.security-headers.headers.stsSeconds=31536000"
- "traefik.http.middlewares.security-headers.headers.stsIncludeSubdomains=true"
- "traefik.http.routers.app.middlewares=security-headers"Rate Limiting
labels:
- "traefik.http.middlewares.rate-limit.ratelimit.average=100"
- "traefik.http.middlewares.rate-limit.ratelimit.burst=50"
- "traefik.http.routers.app.middlewares=rate-limit"IP Whitelist
labels:
- "traefik.http.middlewares.whitelist.ipwhitelist.sourcerange=192.168.1.0/24,10.0.0.0/8"
- "traefik.http.routers.app.middlewares=whitelist"Strip Prefix
labels:
# Retire /api du path avant d'envoyer au service
- "traefik.http.middlewares.strip-api.stripprefix.prefixes=/api"
- "traefik.http.routers.app.middlewares=strip-api"Chaîner les middlewares
labels:
- "traefik.http.routers.app.middlewares=redirect-https,security-headers,rate-limit"Certificats SSL
Let’s Encrypt automatique
# Dans traefik.yml
certificatesResolvers:
letsencrypt:
acme:
email: ton@email.com
storage: acme.json
httpChallenge:
entryPoint: http# Dans le service
labels:
- "traefik.http.routers.app.tls=true"
- "traefik.http.routers.app.tls.certresolver=letsencrypt"Wildcard avec DNS Challenge (Cloudflare)
# Dans traefik.yml
certificatesResolvers:
letsencrypt:
acme:
email: ton@email.com
storage: acme.json
dnsChallenge:
provider: cloudflare
resolvers:
- "1.1.1.1:53"
- "8.8.8.8:53"# Variables d'environnement pour Traefik
environment:
- CF_API_EMAIL=ton@email.com
- CF_API_KEY=ton-api-key# Dans le service
labels:
- "traefik.http.routers.app.tls.certresolver=letsencrypt"
- "traefik.http.routers.app.tls.domains[0].main=example.com"
- "traefik.http.routers.app.tls.domains[0].sans=*.example.com"Dashboard Traefik
Accès sécurisé au dashboard
services:
traefik:
labels:
- "traefik.enable=true"
- "traefik.http.routers.dashboard.rule=Host(`traefik.example.com`)"
- "traefik.http.routers.dashboard.entrypoints=https"
- "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.middlewares=auth"
- "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$..."Exemples complets
Application web classique
version: '3.8'
services:
app:
image: nginx:alpine
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.app.rule=Host(`app.example.com`)"
- "traefik.http.routers.app.entrypoints=https"
- "traefik.http.routers.app.tls.certresolver=letsencrypt"
- "traefik.http.services.app.loadbalancer.server.port=80"
- "traefik.http.routers.app.middlewares=security-headers"
networks:
- proxy
networks:
proxy:
external: trueAPI avec sous-chemin
version: '3.8'
services:
api:
image: mon-api
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`example.com`) && PathPrefix(`/api`)"
- "traefik.http.routers.api.entrypoints=https"
- "traefik.http.routers.api.tls.certresolver=letsencrypt"
- "traefik.http.services.api.loadbalancer.server.port=8080"
- "traefik.http.middlewares.api-strip.stripprefix.prefixes=/api"
- "traefik.http.routers.api.middlewares=api-strip,rate-limit"
networks:
- proxy
networks:
proxy:
external: trueStack complète avec base de données
version: '3.8'
services:
frontend:
image: mon-frontend
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.frontend.rule=Host(`app.example.com`)"
- "traefik.http.routers.frontend.entrypoints=https"
- "traefik.http.routers.frontend.tls.certresolver=letsencrypt"
- "traefik.http.services.frontend.loadbalancer.server.port=80"
networks:
- proxy
- internal
backend:
image: mon-backend
restart: unless-stopped
environment:
- DATABASE_URL=postgres://user:pass@db:5432/app
labels:
- "traefik.enable=true"
- "traefik.http.routers.backend.rule=Host(`app.example.com`) && PathPrefix(`/api`)"
- "traefik.http.routers.backend.entrypoints=https"
- "traefik.http.routers.backend.tls.certresolver=letsencrypt"
- "traefik.http.services.backend.loadbalancer.server.port=3000"
networks:
- proxy
- internal
db:
image: postgres:15-alpine
restart: unless-stopped
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=app
networks:
- internal
volumes:
postgres_data:
networks:
proxy:
external: true
internal:Commandes utiles
# Créer le network proxy
docker network create proxy
# Créer le fichier acme.json avec les bonnes permissions
touch acme.json && chmod 600 acme.json
# Voir les logs de Traefik
docker logs -f traefik
# Générer un hash pour Basic Auth
echo $(htpasswd -nb user password) | sed -e s/\\$/\\$\\$/gDebugging
Active le mode debug temporairement pour diagnostiquer les problèmes.
# Dans traefik.yml
log:
level: DEBUG
accessLog: {}Vérifier la configuration
# Voir les routers configurés
curl http://localhost:8080/api/http/routers | jq
# Voir les services
curl http://localhost:8080/api/http/services | jq
# Voir les middlewares
curl http://localhost:8080/api/http/middlewares | jq