Pourquoi Traefik v3 plutôt que nginx pour votre stack Docker
nginx est un excellent serveur HTTP, mais sa configuration est statique : chaque nouveau service nécessite un nouveau fichier de vhost, un rechargement du processus et souvent une modification manuelle du renouvellement ACME. Traefik a été conçu pour les environnements conteneurisés où la topologie change constamment. En version 3, il pousse cette logique encore plus loin avec le support natif de HTTP/3 (QUIC), une syntaxe de middlewares simplifiée et un runtime plus strict qui sécurise les configurations ambiguës.
- Découverte automatique des conteneurs via les labels Docker — aucun rechargement manuel quand vous ajoutez un service.
- HTTPS automatique avec Let's Encrypt (challenge TLS-ALPN-01 ou HTTP-01) : certificats obtenus, stockés et renouvelés sans intervention.
- Middlewares natifs déclarables par label : BasicAuth, rate-limit, headers de sécurité, redirections — sans écrire de module nginx.
- Dashboard temps réel intégré : visualisez toutes les routes, middlewares et état des certificats depuis un navigateur.
- Support HTTP/3 (QUIC) en une ligne de configuration : améliore la performance sur les connexions à forte latence.
- Routage par Host, PathPrefix, Headers ou toute combinaison — les règles s'écrivent en Go template expressif.
- API REST interne : interrogez l'état du routeur, inspectez les backends actifs, automatisez des intégrations CI/CD.
- Compatible Docker Swarm, Kubernetes et Nomad — vous pouvez migrer sans changer vos labels.
Prérequis techniques avant de commencer
Cette installation nécessite un VPS sous Debian 12 ou Ubuntu 22.04/24.04 (les commandes sont identiques), Docker Engine 25+ et Docker Compose v2.24+ (la commande docker compose sans tiret). Vérifiez que les ports 80 et 443 sont ouverts dans votre pare-feu — en entrée depuis Internet. Vous aurez besoin d'un nom de domaine dont vous contrôlez les DNS : pointez un enregistrement A sur l'IP de votre VPS avant de commencer, sans quoi Let's Encrypt ne pourra pas émettre le certificat. Un compte e-mail valide est requis pour les notifications d'expiration ACME.
Installation complète de Traefik v3 étape par étape
Créer le réseau Docker partagé. Traefik doit être sur le même réseau que les services qu'il proxifie. Créez-le une seule fois :
docker network create traefik-public. Ce réseau sera référencé dans chaquedocker-compose.ymlde vos services.Créer le fichier
acme.jsonpour les certificats. Let's Encrypt écrira ses certificats dans ce fichier. Il doit appartenir à root avec les permissions 600 strictement :touch /opt/traefik/acme.json && chmod 600 /opt/traefik/acme.json. Si les permissions sont incorrectes, Traefik refusera de démarrer.Créer le
docker-compose.ymlTraefik. Placez ce fichier dans/opt/traefik/docker-compose.yml:services: traefik: image: traefik:v3.3 container_name: traefik restart: unless-stopped ports: - "80:80" - "443:443" - "443:443/udp" # HTTP/3 QUIC command: - "--api.dashboard=true" - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:80" - "--entrypoints.web.http.redirections.entrypoint.to=websecure" - "--entrypoints.web.http.redirections.entrypoint.scheme=https" - "--entrypoints.websecure.address=:443" - "--entrypoints.websecure.http3=true" - "--certificatesresolvers.letsencrypt.acme.tlschallenge=true" - "--certificatesresolvers.letsencrypt.acme.email=admin@votre-domaine.com" - "--certificatesresolvers.letsencrypt.acme.storage=/acme.json" - "--log.level=INFO" volumes: - "/var/run/docker.sock:/var/run/docker.sock:ro" - "./acme.json:/acme.json" networks: - traefik-public labels: - "traefik.enable=true" - "traefik.http.routers.dashboard.rule=Host(`traefik.votre-domaine.com`)" - "traefik.http.routers.dashboard.entrypoints=websecure" - "traefik.http.routers.dashboard.tls.certresolver=letsencrypt" - "traefik.http.routers.dashboard.service=api@internal" - "traefik.http.routers.dashboard.middlewares=dashboard-auth" - "traefik.http.middlewares.dashboard-auth.basicauth.users=admin:$$2y$$10$$abc..." networks: traefik-public: external: trueGénérer le hash BasicAuth pour le dashboard. Remplacez la chaîne en dur par un vrai hash bcrypt généré avec :
echo $(htpasswd -nB admin) | sed -e 's/\$/\$\$/g'. La commandehtpasswdest dans le paquetapache2-utilssous Debian/Ubuntu. Les signes$doivent être doublés ($$) dans la valeur du label Docker Compose.Démarrer Traefik. Depuis
/opt/traefik/:docker compose up -d. Vérifiez les logs :docker compose logs -f traefik. Vous devriez voir"Starting provider" providerType=Dockerpuis"Attaching router" routerName=dashboard. Si vous voyez une erreur suracme.json, vérifiez les permissions.Ajouter un service derrière Traefik. Voici un exemple avec une application web Node.js. Dans son propre
docker-compose.yml:services: monapp: image: monapp:latest restart: unless-stopped networks: - traefik-public labels: - "traefik.enable=true" - "traefik.http.routers.monapp.rule=Host(`app.votre-domaine.com`)" - "traefik.http.routers.monapp.entrypoints=websecure" - "traefik.http.routers.monapp.tls.certresolver=letsencrypt" - "traefik.http.services.monapp.loadbalancer.server.port=3000" networks: traefik-public: external: trueDès que vous faites
docker compose up -d, Traefik détecte le conteneur, obtient le certificat et la route est active — sans toucher à sa propre configuration.Vérifier les certificats Let's Encrypt. Inspectez le fichier
acme.json:cat /opt/traefik/acme.json | python3 -m json.tool | grep -A3 'domain'. Vous devez voir vos domaines listés avec une date d'expiration à 90 jours. Alternativement, le dashboard Traefik surtraefik.votre-domaine.comliste tous les certificats actifs sous l'onglet *Routers*.Valider la redirection HTTP→HTTPS. Testez avec curl :
curl -v http://app.votre-domaine.com. Vous devez recevoir un301 Moved Permanentlyvershttps://. Si vous obtenez une connexion refusée sur le port 80, vérifiez que les règles de pare-feu autorisent ce port.Activer HTTP/3 côté navigateur. Ajoutez le header
Alt-Svcvia un middleware global dans vos labels Traefik ou dans un fichier de configuration statiquetraefik.yml. Le headerAlt-Svc: h3=":443"; ma=86400indique au navigateur que votre serveur supporte QUIC. Vérifiez l'activation aveccurl --http3 https://app.votre-domaine.com -v.
Middlewares essentiels : BasicAuth, rate-limit et headers de sécurité
Les middlewares Traefik s'appliquent par label Docker directement sur le routeur du service concerné. Voici les trois middlewares les plus utiles en production, déclarés sur le service lui-même sans toucher à la configuration centrale de Traefik.
- BasicAuth sur une route privée — pour protéger un outil d'administration (Adminer, Flower, etc.) : ajoutez les labels
traefik.http.middlewares.adminauth.basicauth.users=admin:$$hash$$ettraefik.http.routers.monadmin.middlewares=adminauthsur le service concerné. - Rate-limit anti-abus — protège une API ou un formulaire de contact :
traefik.http.middlewares.ratelimit.ratelimit.average=100(100 requêtes/seconde en moyenne),traefik.http.middlewares.ratelimit.ratelimit.burst=50(rafale de 50 tolérée). Appliquez ensuite le middleware sur le routeur :traefik.http.routers.monapi.middlewares=ratelimit. - Headers de sécurité HTTP —
X-Frame-Options,X-Content-Type-Options,Strict-Transport-Security: le middlewareheadersde Traefik accepte toutes ces valeurs directement en label, sans fichier de configuration nginx séparé. - Redirect Regex — pour rediriger
www.votre-domaine.comversvotre-domaine.com: utilisez le middlewareredirectregexavecpermanent=trueet une regex^https://www\.(.+)→https://${1}. - Compress — activez la compression gzip/brotli sur toutes les réponses textuelles avec un seul label :
traefik.http.middlewares.compress.compress=true. Appliquez-le globalement en l'ajoutant comme middleware par défaut dans la configuration statique.
HTTP/3 (QUIC) en deux lignes. Dans la section command du docker-compose.yml Traefik, ajoutez --entrypoints.websecure.http3=true et exposez le port UDP 443 (443:443/udp). Le protocole QUIC établit les connexions jusqu'à 30 % plus vite sur des réseaux à pertes, et élimine le head-of-line blocking de TLS-sur-TCP. Les navigateurs modernes (Chrome 87+, Firefox 88+, Safari 16.4+) l'activent automatiquement après le premier échange via l'en-tête Alt-Svc. Aucune modification côté application n'est nécessaire.
Migration depuis Traefik v2 : les changements cassants
Traefik v3 introduit des ruptures intentionnelles avec v2 pour nettoyer les ambiguïtés accumulées. La bonne nouvelle : la migration est progressive — vous pouvez faire coexister des configurations v2 et v3 pendant la transition. Voici les points qui cassent le plus fréquemment.
docker.swarmModerenommé endocker.swarmmode(tout en minuscules). Si votre configuration v2 utilise l'ancienne casse, Traefik v3 l'ignore silencieusement et la découverte Swarm ne fonctionne pas.- Règle
PathPrefixsans slash trailing : en v3,PathPrefix('/api')est équivalent àPathPrefix('/api/')— le trailing slash est normalisé. Si vous aviez des règles qui dépendaient de ce comportement pour discriminer/apide/apiv2, révisez-les. tls.certificatesen configuration dynamique : en v2, on pouvait définir des certificats manuels directement dans la configuration dynamique d'un fournisseur de fichiers. En v3, cette section doit être dans la configuration statique (traefik.yml) ou via un fournisseur dédié.- Middleware
errors: le paramètrequeryest renommé enurl. Toute configuration qui utilisaiterrors.querydoit être mise à jour verserrors.url. - Suppression du support du protocole
spiffe: si vous utilisiez l'authentification SPIFFE dans une infrastructure Consul, migrez vers une solution de mTLS standard avant de passer à v3. - Configuration Docker
constraints: la syntaxe des contraintes a changé pour s'aligner sur le format standard des tags Docker. Vérifiez votre liste de contraintes si vous filtriez les services par tag.
Traefik v3 vs nginx vs Caddy : quel reverse proxy pour Docker ?
Faites défiler le tableau
| Critère | Traefik v3 | nginx | Caddy v2 |
|---|---|---|---|
| Configuration | Labels Docker, TOML ou YAML — rechargement automatique à chaud | Fichiers vhost statiques — rechargement manuel (`nginx -s reload`) | Caddyfile déclaratif — rechargement automatique à chaud |
| HTTPS automatique | Intégré nativement (ACME v2, challenge TLS-ALPN ou HTTP-01) | Requiert certbot + cron + script de rechargement | Intégré nativement, le plus simple à configurer (une ligne) |
| Routing dynamique Docker | Natif : découverte en temps réel des conteneurs via le socket Docker | Non natif : nécessite nginx-proxy ou modification manuelle | Natif via le plugin caddy-docker-proxy (non officiel) |
| HTTP/3 (QUIC) | Supporté nativement depuis v3 (2024), activable en une ligne | Supporté depuis nginx 1.25 (2023), configuration supplémentaire | Supporté nativement depuis Caddy 2.6 (2022) |
| Performances brutes | Légèrement inférieur à nginx sur les très hauts débits (>50k req/s) | Référence industrielle pour les débits élevés et la concurrence | Comparable à nginx sur la plupart des charges web standard |
| Courbe d'apprentissage | Modérée — concepts de routeur/service/middleware à assimiler | Élevée pour HTTPS + Docker — documentation fragmentée | Faible — la configuration la plus concise pour des cas simples |
Dépannage : les cinq erreurs les plus fréquentes
La majorité des problèmes Traefik en production viennent de trois sources : les permissions du fichier acme.json, le réseau Docker manquant, et les labels mal échappés dans Compose. Voici les erreurs avec leurs messages réels.
level=error msg="Unable to obtain ACME certificate" error="acme: error 403"ouunauthorized— Let's Encrypt ne peut pas vérifier votre domaine. Vérifiez que le port 80 est ouvert depuis Internet (curl http://votre-domaine.comdepuis une machine externe) et que le DNS de votre domaine pointe bien sur l'IP du VPS (dig +short votre-domaine.com).level=error msg="The acme.json file has bad file permissions"puis Traefik refuse de démarrer — les permissions du fichier ne sont pas 600. Corrigez :chmod 600 /opt/traefik/acme.json. Ce check est intentionnellement bloquant : un fichier lisible par d'autres utilisateurs exposerait vos clés privées.- Service accessible depuis le dashboard Traefik mais erreur 502 Bad Gateway — le conteneur du service n'est pas sur le réseau
traefik-public. Vérifiez avecdocker inspect <container> | grep -A20 Networks. Ajoutez le réseau dans ledocker-compose.ymldu service et recréez le conteneur. - Labels ignorés silencieusement, route absente du dashboard — vous avez oublié
traefik.enable=truesur le service, ou--providers.docker.exposedbydefault=falseest actif (recommandé) et le label est absent. Vérifiez aussi que le nom du routeur danstraefik.http.routers.<nom>.ruleest unique parmi tous vos services. invalid character '$' in label value— les signes$dans les hashes BasicAuth ne sont pas doublés dans le fichier Compose. La syntaxe correcte est$$2y$$10$$...(chaque$devient$$) quand la valeur est dans undocker-compose.yml. Si vous passez la valeur via une variable d'environnement, un seul$suffit.
Prochaine étape : hardener votre stack Docker en production
Traefik v3 gère le routing et le TLS, mais une stack Docker production-ready demande davantage : healthchecks sur les conteneurs, politique de redémarrage, logs centralisés, rotation des secrets, sauvegardes des volumes. Consultez notre guide docker-compose-production-checklist pour une liste de contrôle complète à appliquer avant de mettre en production n'importe quel service conteneurisé sur votre VPS.