SSD Nodes Learn Hosting plans →
Guides Matt ConnorPar Matt Connor · Mis à jour le 2026-08-22

Migration Traefik v2 vers v3 : ce qui casse

Traefik v3 refuse de démarrer avec swarmMode ou pilot dans la configuration statique. Corrigez « incompatible deprecated static option found », puis migrez vos règles.

Ce qui change entre Traefik v2 et v3

La migration de Traefik v2 vers v3 consiste principalement à renommer des éléments. Le renommage le plus connu concerne le middleware ipWhiteList, devenu ipAllowList. En outre, v3 durcit la syntaxe des règles des routeurs : PathPrefix perd ses fonctionnalités liées aux expressions régulières, plusieurs matchers sont renommés ou supprimés, et quelques providers et options sont entièrement abandonnés. Le reste continue de fonctionner : les entrypoints, la configuration des certificats ACME, le workflow basé sur les labels Docker et votre acme.json sont conservés. v3 fournit aussi un mode de compatibilité qui permet de continuer à utiliser la syntaxe des règles de v2. Vous pouvez donc mettre à niveau le binaire d’abord, puis réécrire les règles service par service, au lieu de tout modifier au cours d’une seule intervention risquée.

Ce guide part de la configuration Docker Compose basée sur les labels présentée dans le guide du reverse proxy Traefik. Cette page utilise nativement v3 ; celle-ci concerne le serveur qui exécute encore un tag traefik:v2.

Renommages et suppressions

  • ipWhiteList devient ipAllowList, pour les middlewares HTTP et TCP. Les options internes restent inchangées, et sourcerange conserve donc exactement sa signification. Les versions v3 actuelles, y compris v3.5, acceptent encore l’ancien nom comme alias obsolète et continuent d’appliquer la liste. Ce renommage ne provoque donc aucune interruption lors du passage à v3. Renommez-le tout de même : la suppression de l’alias est prévue, et il disparaîtra de la liste des éléments obsolètes sans avertissement explicite.
  • providers.docker.swarmMode=true a été supprimé. Swarm dispose de son propre provider, configuré avec providers.swarm.endpoint.
  • La section pilot a été entièrement supprimée.
  • experimental.http3 a été supprimé. HTTP/3 est directement activé sur l’entrypoint.
  • tls.caOptional a été supprimé des providers et du middleware forwardAuth. Si ce middleware est placé devant un SSO Authentik auto-hébergé, supprimer la ligne caOptional constitue toute la migration nécessaire, car l’adresse de forwardAuth, les en-têtes approuvés et l’outpost associé se comportent de la même manière dans v3.
  • Le provider de métriques InfluxDB v1, le provider Rancher et le provider Marathon ont été supprimés.
  • Le tracing utilise désormais OpenTelemetry. Les backends de tracing dédiés, notamment les intégrations Jaeger et Zipkin, ont été supprimés. v3 exporte à la place des données au format OTLP (le protocole OpenTelemetry).
  • Les options ssl* obsolètes du middleware headers (sslRedirect, sslHost et les autres) ont été supprimées. Les redirections des entrypoints et le middleware redirectScheme les remplacent.

Ces suppressions sont plus importantes qu’elles n’en ont l’air, car Traefik refuse de démarrer lorsque sa configuration statique contient une option inconnue. Une ligne pilot ou swarmMode restante arrête le conteneur au démarrage avec un message incompatible deprecated static option found qui indique l’élément restant. Une option que Traefik n’a jamais connue, par exemple une faute de frappe ou tls.caOptional, provoque à la place un message field not found. Nettoyez la configuration statique avant de modifier le tag de l’image.

Un nom de middleware que Traefik ne connaît réellement pas, par exemple une faute de frappe ou un nom supprimé plutôt que conservé comme alias, échoue autrement : le router qui le référence est chargé avec une erreur au lieu de créer une route, le dashboard le signale et l’API renvoie middleware "offce@docker" does not exist. Les requêtes destinées à ce hostname reçoivent une réponse 404, car le router n’a jamais été activé. Notez que ipwhitelist n’entre PAS dans cette catégorie avec les versions v3 actuelles : il reste disponible comme alias obsolète. Un label qui n’a pas été renommé continue donc de fonctionner sans alerte.

La syntaxe des règles change

Les règles permettent d’effectuer les réécritures proprement dites. Voici les changements de la v3 :

  • Les valeurs utilisées dans les matchers doivent être entourées de backticks. La v2 acceptait également les guillemets doubles ; ce n’est plus le cas en v3. Host("app.example.com") doit donc devenir Host(app.example.com).
  • PathPrefix ne prend plus en charge les expressions régulières ni les placeholders de type {id}. Une règle v2 telle que PathPrefix(/api/{version:v[0-9]+}) doit devenir un matcher PathRegexp utilisant la syntaxe des expressions régulières Go.
  • Les matchers n’acceptent désormais qu’une seule valeur. La v2 autorisait Host(app.example.com,www.example.com) ; en v3, utilisez Host(app.example.com) || Host(www.example.com). Les exceptions sont Header, HeaderRegexp, Query et QueryRegexp, qui acceptent toujours un nom et une valeur.
  • Headers et HeadersRegexp sont renommés en Header et HeaderRegexp.
  • HostHeader est supprimé. Utilisez Host, qui correspond au même élément en v3.
  • Deux matchers sont nouveaux : QueryRegexp et ClientIP, qui permet de faire correspondre l’adresse du client dans une règle.

La bonne nouvelle est qu’une règle simple Host(app.example.com) écrite avec des backticks est déjà valide en syntaxe v3. La plupart des configurations Compose de petite taille utilisent exactement cette forme. La migration de la plupart des labels ne nécessite donc aucune modification des règles.

Auditez vos labels avant de commencer

Vous pouvez mesurer l’ampleur de la migration avec une seule recherche, car chaque modification incompatible d’un label laisse un motif que grep peut trouver :

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

Chaque résultat correspond à une ligne à modifier. ipwhitelist devient ipallowlist. HostHeader devient Host. Headers devient Header. Un placeholder {...} à l’intérieur de PathPrefix devient un matcher PathRegexp. Une virgule dans Host() devient deux matchers Host() reliés par ||. Zéro résultat signifie que vos labels utilisent déjà une syntaxe v3 valide et que la migration se limite à la configuration statique et au tag de l’image. Une page entière de résultats est également un bon moment pour vous demander si ce proxy est toujours adapté à ce serveur ; la comparaison entre Traefik, Nginx et Caddy met le coût de cette réécriture en regard de ce que les deux autres vous demandent pour chaque application.

Ce qui reste inchangé

Les points d’entrée et leur redirection HTTP vers HTTPS, les résolveurs ACME avec leurs deux types de challenge, exposedByDefault, les labels des routeurs et des services, loadbalancer.server.port et le tableau de bord fonctionnent en v3 comme en v2. Vos certificats sont également conservés, car v3 continue de lire le acme.json créé par v2. Sauvegardez tout de même ce fichier avant de commencer : un rollback qui le perd vous expose directement à la limite de débit de Let’s Encrypt concernant les certificats en double :

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

Le chemin de migration

Étape 1 : figez ce que vous exécutez aujourd’hui. Remplacez chaque tag traefik:latest ou traefik:v2 par la release exacte que vous utilisez, par exemple traefik:v2.11, puis commitez l’intégralité du répertoire Compose dans git. Toutes les étapes suivantes deviennent réversibles avec un checkout. Si recréer un seul service avec docker compose up -d <service> ne vous est pas encore familier, le guide sur les bases de Docker Compose présente les opérations utilisées dans cette migration.

Étape 2 : nettoyez la configuration statique et activez le mode de compatibilité. Supprimez toutes les options supprimées en v3 (pilot, swarmMode, tls.caOptional, experimental.http3), puis indiquez à v3 d’interpréter par défaut les règles avec la syntaxe v2. Dans traefik.yml :

core:
  defaultRuleSyntax: v2

Vous pouvez aussi utiliser un flag dans la liste compose command: : --core.defaultRuleSyntax=v2. Le mode de compatibilité couvre uniquement la syntaxe des règles. Il ne rétablit pas les options supprimées et ne renomme pas les middlewares à votre place.

Étape 3 : préparez le renommage des middlewares. Recherchez les anciens noms dans vos fichiers Compose : grep -rn ipwhitelist docker-compose*.yml. Modifiez chaque label ipwhitelist en ipallowlist, mais n’appliquez pas encore la modification, car le nouveau nom n’existe pas en v2. Ces modifications seront déployées avec le basculement de l’étape suivante. (Si un ancien nom vous échappe, la version v3 actuelle le reconnaît encore comme alias obsolète, donc la liste continue de s’appliquer ; corrigez-le lors du passage suivant plutôt qu’à 2 h du matin.)

Étape 4 : basculez le tag de l’image. Définissez l’image Traefik sur la release v3 actuelle, traefik:v3.5 au moment de la rédaction, puis :

docker compose up -d
docker compose logs -f traefik

Comme le mode de compatibilité est activé, vos règles v2 continuent de fonctionner. De plus, comme up -d a également recréé les services dont vous avez renommé les labels de middleware, leurs routers démarrent correctement. Des journaux sains ne contiennent ni ligne field not found ni ligne does not exist.

Soyez conscient de la fenêtre d’indisponibilité créée par cette étape. Un router qui référence un nom de middleware que v3 ne connaît réellement pas (à cause d’une faute de frappe ou d’une option supprimée) est indisponible dès le démarrage du nouveau Traefik et jusqu’à la recréation de son conteneur d’application. Sur un serveur, cela dure les quelques secondes dont docker compose up -d a besoin pour parcourir la liste. Si une route ne peut vraiment pas subir la moindre interruption, retirez le middleware renommé du label middlewares de ce router avant le basculement, puis ajoutez-le de nouveau après. Déterminez à l’avance si cette route peut fonctionner sans sa liste d’autorisation IP pendant la minute intermédiaire.

Étape 5 : migrez les règles service par service. Traitez une application à la fois : réécrivez sa règle avec la syntaxe v3, recréez uniquement ce service avec docker compose up -d app, puis testez-le avant de poursuivre. Si un service possède une règle que vous ne pouvez pas encore réécrire, ajoutez à ce router le label de contournement traefik.http.routers.app.ruleSyntax=v2 et continuez.

Étape 6 : désactivez le mode de compatibilité. Lorsque toutes les règles utilisent la syntaxe v3, supprimez defaultRuleSyntax ainsi que les labels ruleSyntax, redémarrez Traefik et vérifiez que tous les routers apparaissent toujours en vert dans le dashboard. Ne conservez pas le mode de compatibilité activé : Traefik a marqué ces deux options comme obsolètes en v3.4 et les supprimera dans la prochaine version majeure. Elles servent de transition, pas de configuration permanente.

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

Voici une application qui cumule tous les changements courants : un Host multivaleur, 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 la 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 séparé son Host multivaleur en deux matchers reliés par || et a remplacé le placeholder par PathRegexp. Le label du middleware a remplacé ipwhitelist par ipallowlist. L’entrypoint, le certificate resolver, la liaison entre le router et le middleware ainsi que le port du service n’ont pas changé.

Tester chaque service avec le dashboard

Après chaque basculement, ouvrez la page des routeurs HTTP du dashboard. Tous les routeurs doivent être verts. Un routeur marqué d’une erreur indique précisément le problème rencontré. Il s’agit généralement d’un middleware qui n’existe plus sous son nouveau nom ou d’une règle que v3 ne peut pas analyser. Vérifiez ensuite le résultat 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 habituelle de votre application signifie que le routage et TLS fonctionnent toujours. Un 404 renvoyé par Traefik signifie que le routeur n’a pas démarré. Retournez au dashboard et consultez son erreur. Gardez docker compose logs -f traefik ouvert dans un second terminal pendant l’opération. Chaque erreur d’analyse y apparaît dès qu’un conteneur redémarre.

Honnêteté du rollback

Conservez le fichier compose v2, sa configuration statique et la sauvegarde acme.json jusqu’à ce que tous les services soient routés sur v3 et aient été utilisés en conditions réelles. Pour effectuer un rollback, revenez au commit précédant la migration, puis exécutez docker compose up -d. Il faut restaurer le fichier complet, et pas seulement le tag de l’image, car les labels propres à v3 sont incorrects sous v2, tout comme les labels v2 étaient incorrects sous v3 : ipallowlist n’existe pas dans v2, et un matcher PathRegexp n’y sera pas analysé non plus. Si acme.json a été perdu ou endommagé en cours de route, restaurez la copie de sauvegarde avant de démarrer v2. Le rollback n’épuisera ainsi pas votre rate limit Let’s Encrypt en réémettant cinq certificats à la fois.

FAQ

Dois-je réécrire toutes les règles de routeur pour Traefik v3 ?

Non. Une règle Host(app.example.com) standard écrite avec des accents graves est valide dans les deux versions, ce qui couvre la plupart des configurations Compose. La réécriture est nécessaire uniquement lorsqu’une règle utilise des fonctionnalités propres à v2 : des expressions régulières ou des variables dans Path et PathPrefix, plusieurs noms d’hôte dans un même Host(), des guillemets à la place des accents graves, ou les matchers supprimés Headers, HeadersRegexp et HostHeader.

Que devient ipWhiteList dans Traefik v3 ?

Le nom a été remplacé par ipAllowList, sans modification de la configuration interne. Ainsi, un label v2 comme traefik.http.middlewares.office.ipwhitelist.sourcerange=10.0.0.0/24 devient la même ligne avec ipallowlist. Les versions actuelles de v3, y compris v3.5, acceptent encore l’ancien nom comme alias obsolète. Un label qui n’a pas été renommé continue donc à appliquer silencieusement l’allowlist. Considérez cette compatibilité comme temporaire et non comme une raison de repousser le renommage : la suppression de l’alias est prévue, et un nom de middleware que Traefik ne connaît réellement pas provoque une erreur visible, avec une erreur de routeur et une réponse 404. Le dashboard affiche l’erreur et les requêtes vers ce nom d’hôte renvoient 404.

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

Oui. Définissez core.defaultRuleSyntax: v2 dans la configuration statique pour conserver la syntaxe v2 par défaut pendant la migration. Utilisez ensuite le label ruleSyntax=v2 au niveau de chaque routeur pour les derniers routeurs non migrés, après avoir rétabli la nouvelle syntaxe par défaut. Ces deux options sont temporaires : Traefik les a déclarées obsolètes dans v3.4 et les supprimera dans la prochaine version majeure.

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

Oui. Traefik v3 continue à lire le fichier acme.json écrit par v2. Les certificats ne sont donc pas réémis simplement parce que le binaire a changé. Copiez malgré tout ce fichier dans un emplacement sûr avant de commencer. Un rollback ou la suppression d’un volume qui contient acme.json oblige à réémettre tous les certificats en même temps, et Let's Encrypt n’autorise que cinq certificats dupliqués par semaine pour le même ensemble de noms d’hôte.

Pourquoi Traefik v3 refuse-t-il de démarrer après la mise à niveau ?

Presque toujours parce que la configuration statique contient encore une option supprimée dans v3. Traefik refuse de démarrer lorsqu’une option n’est pas reconnue. Pour les options obsolètes connues (pilot, providers.docker.swarmMode, experimental.http3), le journal indique incompatible deprecated static option found et nomme l’option concernée. Pour une option que v3 n’a jamais reconnue, comme tls.caOptional, il indique field not found avec le nœud concerné. Supprimez ou remplacez chaque option, puis redémarrez le conteneur.