SSD Nodes Learn
Guides Matt ConnorPar Matt Connor · Mis à jour le 2026-07-19

Migration Traefik v2 vers v3, pas à pas

Traefik v3 renomme ipWhiteList en ipAllowList et modifie la syntaxe des règles. Passez de v2 au mode compatibilité, puis migrez les labels un service à la fois.

Ce qui change entre Traefik v2 et v3

Une migration de Traefik v2 vers v3 est surtout un travail de renommage, et le renommage le plus connu est le middleware ipWhiteList qui devient ipAllowList. Au-delà de cela, v3 resserre la syntaxe des règles de routeur (PathPrefix perd ses fonctions d'expressions régulières, plusieurs matchers sont renommés ou supprimés), supprime purement et simplement quelques providers et options, et garde tout le reste fonctionnel : les entrypoints, la configuration des certificats ACME, le workflow des labels Docker et votre acme.json sont tous conservés. v3 fournit aussi un mode compatibilité qui garde la syntaxe des règles v2 fonctionnelle, ce qui vous permet de mettre à jour le binaire d'abord et de réécrire les règles un service à la fois plutôt qu'en une seule soirée risquée.

Ce guide suppose la configuration Docker Compose basée sur les labels du guide du proxy inverse Traefik. Cette page est native v3 ; celle-ci est pour la machine qui utilise encore un tag traefik:v2.

Les renommages et suppressions

  • ipWhiteList est maintenant ipAllowList, pour le middleware HTTP comme pour le TCP. Les options à l'intérieur ne changent pas, donc sourcerange garde son sens exact. Les versions v3 actuelles, y compris v3.5, acceptent encore l'ancien nom comme alias déprécié et continuent d'appliquer la liste, donc ce seul renommage ne met rien hors service au moment du basculement. Renommez-le quand même : l'alias est prévu pour suppression, et il disparaît de la liste de dépréciation en silence, pas bruyamment.
  • providers.docker.swarmMode=true a disparu. Swarm obtient son propre provider, configuré comme providers.swarm.endpoint.
  • La section pilot a entièrement disparu.
  • experimental.http3 a disparu. HTTP/3 est activé directement sur l'entrypoint.
  • tls.caOptional a disparu des providers et du middleware forwardAuth.
  • Le provider de métriques InfluxDB v1, le provider Rancher et le provider Marathon ont disparu.
  • Le tracing est passé à OpenTelemetry. Les backends de tracing dédiés, dont les intégrations Jaeger et Zipkin, ont disparu, et v3 exporte OTLP (le protocole OpenTelemetry) à la place.
  • Les options ssl* dépréciées dans le middleware headers (sslRedirect, sslHost et les autres) ont disparu. Les redirections d'entrypoint et le middleware redirectScheme les ont remplacées.

Ces suppressions comptent plus qu'il n'y paraît, car Traefik refuse de démarrer quand sa configuration statique contient une option qu'il ne connaît pas. Une ligne pilot ou swarmMode oubliée arrête le conteneur au démarrage avec un message incompatible deprecated static option found qui nomme l'élément oublié ; une option dont Traefik n'a tout simplement jamais entendu parler (une faute de frappe, ou tls.caOptional) l'arrête plutôt avec field not found. Nettoyez la configuration statique avant de toucher au tag de l'image.

Un nom de middleware que Traefik ne connaît réellement pas (une faute de frappe, ou un nom supprimé plutôt qu'aliasé) échoue différemment : le routeur qui le référence se charge avec une erreur au lieu d'une route, le dashboard le signale, et l'API rapporte middleware "offce@docker" does not exist. Les requêtes vers ce nom d'hôte reçoivent une 404 car le routeur n'est jamais monté. Notez que ipwhitelist n'est PAS dans cette catégorie sur la v3 actuelle : il survit comme alias déprécié, donc un label non renommé continue de fonctionner discrètement.

Les changements de syntaxe des règles

C'est dans les règles que peut se produire une vraie réécriture. Les changements en v3 :

  • Les backticks sont obligatoires autour des valeurs dans les matchers. v2 acceptait aussi les guillemets doubles ; v3 non, donc Host("app.example.com") doit devenir Host(app.example.com).
  • PathPrefix ne comprend plus les expressions régulières ni les placeholders de style {id}. Une règle v2 comme PathPrefix(/api/{version:v[0-9]+}) doit devenir un matcher PathRegexp écrit dans la syntaxe des expressions régulières de Go.
  • Les matchers prennent désormais une seule valeur. v2 permettait Host(app.example.com,www.example.com) ; v3 veut Host(app.example.com) || Host(www.example.com). Les exceptions sont Header, HeaderRegexp, Query et QueryRegexp, qui prennent encore un nom plus une valeur.
  • Headers et HeadersRegexp sont renommés en Header et HeaderRegexp.
  • HostHeader est supprimé. Utilisez Host, qui correspond à la même chose en v3.
  • Deux matchers sont nouveaux : QueryRegexp, et ClientIP pour faire correspondre l'adresse du client dans une règle.

La bonne nouvelle : une simple règle Host(app.example.com) écrite avec des backticks est déjà de la syntaxe v3 valide. La plupart des petites configurations Compose utilisent exactement cela, ce qui signifie que la plupart des labels migrent sans aucune modification de règle.

Auditez vos labels avant de commencer

Vous pouvez mesurer l'ampleur de votre migration avec une seule recherche, car chaque changement de label cassant laisse un motif que grep peut trouver :

grep -rnE 'ipwhitelist|HostHeader|Headers\(|PathPrefix\(`[^`]*\{|Host\(`[^`]*`,' docker-compose*.yml

Chaque résultat est une ligne à modifier. ipwhitelist devient ipallowlist. HostHeader devient Host. Headers devient Header. Un placeholder {...} dans PathPrefix devient un matcher PathRegexp. Une virgule dans Host() devient deux matchers Host() joints par ||. Zéro résultat signifie que vos labels sont déjà de la syntaxe v3 valide, et la migration se réduit à la configuration statique plus le tag de l'image.

Ce qui reste identique

Les entrypoints et leur redirection HTTP vers HTTPS, les resolvers ACME avec les deux types de challenge, exposedByDefault, les labels de routeur et de service, loadbalancer.server.port et le dashboard fonctionnent tous en v3 comme ils le faisaient en v2. Vos certificats sont conservés eux aussi, car v3 continue de lire l'acme.json que v2 a écrit. Sauvegardez quand même le fichier avant de commencer, car un rollback qui le perd tombe directement sur la limite de débit des certificats en double de Let's Encrypt :

cp ./letsencrypt/acme.json ./letsencrypt/acme.json.v2-backup

Le chemin de migration

Étape 1 : figez ce que vous exécutez aujourd'hui. Changez tout tag traefik:latest ou traefik:v2 vers la version exacte sur laquelle vous êtes, par exemple traefik:v2.11, et committez tout le répertoire compose dans git. Chaque étape ultérieure devient réversible avec un checkout. Si recréer un seul service avec docker compose up -d <service> n'est pas encore un réflexe, le guide des bases de Docker Compose couvre les opérations sur lesquelles s'appuie cette migration.

Étape 2 : nettoyez la configuration statique et activez le mode compatibilité. Supprimez toutes les options que v3 a abandonnées (pilot, swarmMode, tls.caOptional, experimental.http3), puis dites à v3 de traiter les règles comme de la syntaxe v2 par défaut. Dans traefik.yml :

core:
  defaultRuleSyntax: v2

Ou comme un flag dans la liste command: de compose : --core.defaultRuleSyntax=v2. Le mode compatibilité couvre uniquement la syntaxe des règles. Il ne ressuscite pas les options supprimées, et il ne renomme pas les middlewares à votre place.

Étape 3 : préparez les renommages de middleware. Cherchez les anciens noms dans vos fichiers compose : grep -rn ipwhitelist docker-compose*.yml. Modifiez chaque label ipwhitelist en ipallowlist, mais n'appliquez pas encore le changement, car le nouveau nom n'existe pas en v2. Ces modifications partent ensemble avec le basculement de l'étape suivante. (Si l'un passe entre les mailles, la v3 actuelle honore encore l'ancien nom comme alias déprécié, donc la liste continue de s'appliquer ; corrigez-le à la passe suivante plutôt qu'à 2h du matin.)

Étape 4 : basculez le tag de l'image. Réglez l'image Traefik sur la version v3 actuelle, traefik:v3.5 au moment de la rédaction, puis :

docker compose up -d
docker compose logs -f traefik

Comme le mode compatibilité est actif, vos règles v2 continuent de correspondre, et comme le up -d a aussi recréé les services dont vous avez renommé les labels de middleware, ces routeurs montent proprement. Un journal sain n'a aucune ligne field not found ni aucune ligne does not exist.

Soyez honnête avec vous-même sur la fenêtre qu'ouvre cette étape. Un routeur qui référence un nom de middleware que v3 ne connaît réellement pas (une faute de frappe, ou une option supprimée) est hors service du moment où le nouveau Traefik démarre jusqu'à ce que son conteneur d'application soit recréé, ce qui sur une seule machine représente les quelques secondes dont docker compose up -d a besoin pour parcourir la liste. Si une route ne peut vraiment pas cligner, retirez le middleware renommé du label middlewares de ce routeur avant le basculement et rajoutez-le après, et décidez à l'avance si cette route peut vivre sans sa liste d'autorisation IP pendant la minute entre les deux.

Étape 5 : migrez les règles service par service. Traitez une application à la fois : réécrivez sa règle en syntaxe v3, recréez uniquement ce service avec docker compose up -d app, et testez-le avant de continuer. Si un service a une règle que vous ne pouvez pas encore réécrire, donnez à ce seul routeur le label de secours traefik.http.routers.app.ruleSyntax=v2 et continuez d'avancer.

Étape 6 : désactivez le mode compatibilité. Quand chaque règle est en syntaxe v3, supprimez defaultRuleSyntax et tous les labels ruleSyntax, redémarrez Traefik, et confirmez que chaque routeur reste vert dans le dashboard. Ne vous installez pas durablement avec le mode compatibilité activé : Traefik a déprécié les deux options en v3.4 et les supprime dans la prochaine version majeure, donc elles sont un pont, pas une destination.

Avant et après : les labels d'un service

Voici une application portant tous les changements connus à la fois : un Host multi-valeurs, un placeholder PathPrefix, et un middleware ipWhiteList. Le bloc v2 :

  app:
    image: app:1.4
    restart: unless-stopped
    networks:
      - proxy
    labels:
      - traefik.enable=true
      - traefik.http.routers.app.rule=Host(`app.example.com`,`www.example.com`) && PathPrefix(`/api/{version:v[0-9]+}`)
      - traefik.http.routers.app.entrypoints=websecure
      - traefik.http.routers.app.tls.certresolver=le
      - traefik.http.routers.app.middlewares=office
      - traefik.http.middlewares.office.ipwhitelist.sourcerange=10.0.0.0/24
      - traefik.http.services.app.loadbalancer.server.port=8080

Et le même service migré vers v3 :

  app:
    image: app:1.4
    restart: unless-stopped
    networks:
      - proxy
    labels:
      - traefik.enable=true
      - traefik.http.routers.app.rule=(Host(`app.example.com`) || Host(`www.example.com`)) && PathRegexp(`^/api/v[0-9]+`)
      - traefik.http.routers.app.entrypoints=websecure
      - traefik.http.routers.app.tls.certresolver=le
      - traefik.http.routers.app.middlewares=office
      - traefik.http.middlewares.office.ipallowlist.sourcerange=10.0.0.0/24
      - traefik.http.services.app.loadbalancer.server.port=8080

Deux labels ont changé. La règle a divisé son Host multi-valeurs en deux matchers joints par || et a remplacé le placeholder par PathRegexp, et le label de middleware a remplacé ipwhitelist par ipallowlist. L'entrypoint, le resolver de certificat, le câblage routeur-vers-middleware et le port du service n'ont pas bougé.

Testez chaque service avec le dashboard

Après chaque basculement, ouvrez la page des routeurs HTTP du dashboard. Chaque routeur devrait être vert. Un routeur avec un badge d'erreur nomme son problème exact, qui est généralement un middleware qui n'existe pas sous son nouveau nom ou une règle que v3 ne peut pas analyser. Confirmez ensuite depuis l'extérieur, un nom d'hôte à la fois :

curl -sI https://app.example.com/api/v1/status

Un 200 ou la redirection normale de votre application signifie que le routage et le TLS ont tous deux survécu. Une 404 de Traefik signifie que le routeur n'est pas monté ; retournez au dashboard et lisez son erreur. Gardez docker compose logs -f traefik ouvert dans un second terminal pendant que vous travaillez, car chaque échec d'analyse y atterrit au moment où un conteneur redémarre.

Honnêteté sur le rollback

Gardez le fichier compose v2, sa configuration statique et la sauvegarde d'acme.json jusqu'à ce que chaque service route sur v3 et ait été éprouvé pour de vrai. Faire un rollback signifie faire un checkout du commit d'avant migration et exécuter docker compose up -d, et ce doit être tout le fichier, pas seulement le tag de l'image, car les labels propres à v3 sont faux sous v2 exactement de la même manière que les labels v2 étaient faux sous v3 : ipallowlist n'existe pas en v2, et un matcher PathRegexp ne s'y analysera pas non plus. Si acme.json a été perdu ou endommagé en chemin, restaurez la copie de sauvegarde avant de démarrer v2, pour que le rollback ne dépense pas votre limite de débit Let's Encrypt à réémettre cinq certificats d'un coup.

FAQ

Dois-je réécrire chaque règle de routeur pour Traefik v3 ?

Non. Une simple règle Host(app.example.com) écrite avec des backticks est valide dans les deux versions, et cela couvre la plupart des configurations Compose. La réécriture n'est nécessaire que là où une règle utilisait des fonctions propres à v2 : regex ou placeholders dans Path et PathPrefix, plusieurs noms d'hôte dans un seul Host(), guillemets au lieu de backticks, ou les matchers supprimés Headers, HeadersRegexp et HostHeader.

Qu'est-il arrivé à ipWhiteList dans Traefik v3 ?

Il a été renommé en ipAllowList, avec la configuration à l'intérieur inchangée, donc un label v2 comme traefik.http.middlewares.office.ipwhitelist.sourcerange=10.0.0.0/24 devient la même ligne avec ipallowlist dedans. Les versions v3 actuelles, y compris v3.5, acceptent encore l'ancien nom comme alias déprécié, donc un label non renommé continue d'appliquer la liste d'autorisation discrètement. Considérez cela comme du temps emprunté plutôt qu'une raison de sauter le renommage : l'alias est prévu pour suppression, et un nom de middleware que Traefik ne connaît réellement pas échoue bruyamment à la place, avec une erreur de routeur et une 404. Le dashboard montre l'erreur, et les requêtes vers ce nom d'hôte renvoient une 404.

Traefik v3 peut-il encore lire la syntaxe des règles v2 ?

Oui. Réglez core.defaultRuleSyntax: v2 dans la configuration statique pour garder la syntaxe v2 par défaut pendant que vous migrez, et utilisez le label ruleSyntax=v2 par routeur pour les retardataires individuels après avoir rebasculé la valeur par défaut. Considérez les deux comme temporaires : Traefik les a dépréciés en v3.4 et les supprime dans la prochaine version majeure.

Mes certificats Let's Encrypt survivront-ils à la mise à jour ?

Oui. Traefik v3 continue de lire le fichier acme.json que v2 a écrit, donc les certificats ne sont pas réémis simplement parce que le binaire a changé. Copiez quand même le fichier dans un endroit sûr avant de commencer, car un rollback ou un volume supprimé qui perd acme.json force la réémission de chaque certificat d'un coup, et Let's Encrypt n'autorise que cinq certificats en double par semaine pour le même ensemble de noms d'hôte.

Pourquoi Traefik v3 ne démarre-t-il pas après la mise à jour ?

Presque toujours parce que la configuration statique contient encore une option que v3 a supprimée, et Traefik refuse de démarrer sur des options qu'il ne reconnaît pas. Pour les oublis bien connus (pilot, providers.docker.swarmMode, experimental.http3) le journal dit incompatible deprecated static option found et nomme le coupable ; pour tout ce dont v3 n'a jamais entendu parler, comme tls.caOptional, il dit field not found avec le nœud. Supprimez ou remplacez chacune, puis redémarrez le conteneur.