Migrazione Traefik v2 a v3: cosa si rompe
Traefik v3 non si avvia con swarmMode o pilot nella configurazione statica. Risolvi l'errore "incompatible deprecated install configuration option", poi aggiorna le regole.
Cosa cambia tra Traefik v2 e v3
La migrazione da Traefik v2 a v3 consiste soprattutto nel rinominare alcuni elementi. Il cambio di nome più noto è quello del middleware ipWhiteList, diventato ipAllowList. Inoltre, v3 rende più rigida la sintassi delle regole dei router: PathPrefix non supporta più le funzionalità regex e diversi matcher sono stati rinominati o rimossi. Alcuni provider e opzioni sono stati eliminati completamente. Il resto continua a funzionare: entrypoint, configurazione dei certificati ACME, flusso di lavoro basato sulle label Docker e il tuo acme.json vengono mantenuti. v3 include anche una modalità di compatibilità che mantiene il supporto per la sintassi delle regole di v2. Puoi quindi aggiornare prima il binario e riscrivere le regole un servizio alla volta, senza eseguire tutte le modifiche in un'unica finestra di manutenzione rischiosa.
Questa guida presuppone la configurazione Docker Compose basata sulle label descritta in guida al reverse proxy Traefik. Quella pagina usa nativamente v3; questa guida è destinata al server che esegue ancora un tag traefik:v2.
Le rinominazioni e le rimozioni
ipWhiteListora èipAllowList, sia per il middleware HTTP sia per quello TCP. Le opzioni al suo interno non cambiano, quindisourcerangeconserva esattamente lo stesso significato. Le release v3 attuali, inclusa la v3.7, accettano ancora il vecchio nome come alias deprecato e continuano ad applicare l’elenco, registrando un avviso di deprecazione. Questa singola rinomina non causa quindi interruzioni durante il passaggio. Esegui comunque la rinomina: il vecchio nome è deprecato e v2.11 comprende giàipAllowList, quindi la modifica può essere applicata prima dell’upgrade.providers.docker.swarmMode=trueè stato rimosso. Swarm dispone di un provider dedicato, configurato comeproviders.swarm.endpoint.- La sezione
pilotè stata rimossa completamente. experimental.http3è stato rimosso. HTTP/3 viene abilitato direttamente sull’entrypoint.tls.caOptionalè stato rimosso dai provider e dal middleware forwardAuth. Se questo middleware precede un SSO Authentik self-hosted, eliminare la rigacaOptionalcompleta la relativa migrazione, perché l’indirizzo forwardAuth, gli header considerati attendibili e l’outpost che li gestisce si comportano allo stesso modo in v3.- Il provider delle metriche InfluxDB v1, il provider Rancher e il provider Marathon sono stati rimossi.
- Il tracing è passato a OpenTelemetry. I backend di tracing dedicati, incluse le integrazioni Jaeger e Zipkin, sono stati rimossi; v3 esporta invece tramite OTLP (il protocollo OpenTelemetry).
- Le opzioni
ssl*deprecate all’interno del middleware headers (sslRedirect,sslHoste le altre) sono state rimosse. Sono state sostituite dai redirect dell’entrypoint e dal middleware redirectScheme.
Queste rimozioni sono più importanti di quanto sembri, perché Traefik non si avvia quando la configurazione statica contiene un’opzione rimossa o sconosciuta. Una riga pilot, swarmMode, experimental.http3 o tls.caOptional rimasta nella configurazione arresta il container durante il boot: Traefik registra prima una riga che identifica l’elemento residuo, ad esempio tls.CAOptional per l’opzione del provider Docker rimossa in v3, quindi termina con incompatible deprecated install configuration option found. Le release fino alla v3.4 riportano l’ultimo messaggio come incompatible deprecated static option found. Un’opzione che Traefik non ha mai riconosciuto, ad esempio a causa di un refuso, arresta il servizio con field not found e il nodo non entra in servizio. Pulisci la configurazione statica prima di modificare il tag dell’immagine.
Un nome di middleware che Traefik non riconosce realmente, a causa di un refuso o perché è stato rimosso anziché mantenuto come alias, produce un errore diverso: il router che lo utilizza viene caricato con un errore anziché con una route, la dashboard lo segnala e l’API restituisce middleware "offce@docker" does not exist. Le richieste dirette a quell’hostname ricevono un 404 perché il router non è mai entrato in servizio. Nota che ipwhitelist NON rientra in questa categoria nelle versioni v3 attuali: rimane disponibile come alias deprecato, quindi un label non rinominato continua a funzionare senza segnalazioni.
La sintassi delle regole cambia
Le regole consentono di applicare le riscritture vere e proprie. In v3 cambiano questi aspetti:
- Le virgolette non rientrano tra le modifiche. Entrambe le versioni accettano i valori delle regole racchiusi tra backtick o tra virgolette doppie con escape e rifiutano le virgolette singole. Di conseguenza, Host(
app.example.com) e Host("app.example.com") con virgolette doppie con escape restano validi così come sono. PathPrefixnon supporta più le espressioni regolari né i segnaposto nello stile{id}. Una regola v2 come PathPrefix(/api/{version:v[0-9]+}) deve diventare un matcherPathRegexpscritto usando la sintassi delle espressioni regolari Go.- I matcher ora accettano un solo valore. La v2 consentiva Host(
app.example.com,www.example.com); la v3 richiede Host(app.example.com) || Host(www.example.com). Le eccezioni sonoHeader,HeaderRegexp,QueryeQueryRegexp, che accettano ancora un nome e un valore. HeaderseHeadersRegexpsono stati rinominati inHeadereHeaderRegexp.HostHeaderè stato rimosso. UsareHost, che nella v3 corrisponde allo stesso criterio.- Sono stati aggiunti due matcher:
PathRegexpeQueryRegexp.ClientIP, che consente di verificare l'indirizzo del client all'interno di una regola, era già presente nella v2.11 e viene mantenuto senza modifiche.
La buona notizia è che una semplice regola Host(app.example.com) scritta con i backtick è già valida nella sintassi v3. La maggior parte delle configurazioni Compose di piccole dimensioni usa esattamente questa forma. Di conseguenza, nella maggior parte dei casi le label possono essere migrate senza modificare le regole.
Verifica le label prima di iniziare
Puoi misurare l'entità della migrazione con una sola ricerca, perché ogni modifica incompatibile alle label lascia un modello che grep può trovare:
grep -rnE 'ipwhitelist|HostHeader|Headers\(|PathPrefix\(`[^`]*\{|Host\(`[^`]*`,' docker-compose*.ymlOgni risultato corrisponde a una riga da modificare. ipwhitelist diventa ipallowlist. HostHeader diventa Host. Headers diventa Header. Un placeholder {...} all'interno di PathPrefix diventa un matcher PathRegexp. Una virgola all'interno di Host() diventa due matcher Host() collegati da ||. Nessun risultato significa che le label usano già una sintassi v3 valida e che la migrazione si riduce alla configurazione statica e al tag dell'immagine. Una schermata piena di risultati è anche un buon momento per chiedersi se questo sia ancora il proxy più adatto al server; il confronto tra Traefik, Nginx e Caddy mette il costo della riscrittura in relazione a ciò che gli altri due richiedono per ogni applicazione.
Cosa resta invariato
Gli entrypoint e il relativo redirect da HTTP a HTTPS, i resolver ACME con entrambi i tipi di challenge, exposedByDefault, le label di router e servizio, loadbalancer.server.port e la dashboard funzionano in v3 come in v2. Anche i certificati vengono mantenuti, perché v3 continua a leggere acme.json, scritto da v2. Esegui comunque un backup del file prima di iniziare: un rollback che lo perda porta direttamente al limite di frequenza di Let's Encrypt per i certificati duplicati:
cp ./letsencrypt/acme.json ./letsencrypt/acme.json.v2-backupIl percorso di migrazione
Passaggio 1: fissa ciò che esegui oggi. Modifica ogni tag traefik:latest o traefik:v2 indicando la release esatta in uso, ad esempio traefik:v2.11, quindi esegui il commit dell'intera directory Compose in git. Ogni passaggio successivo potrà essere annullato con un checkout. Se la ricreazione di un singolo servizio tramite docker compose up -d <service> non ti è ancora familiare, la guida alle basi di Docker Compose descrive le operazioni utilizzate da questa migrazione.
Passaggio 2: pulisci la configurazione statica e attiva la modalità di compatibilità. Rimuovi tutte le opzioni eliminate dalla v3 (pilot, swarmMode, tls.caOptional, experimental.http3), quindi configura la v3 affinché interpreti per impostazione predefinita le regole come sintassi v2. In traefik.yml:
core:
defaultRuleSyntax: v2In alternativa, specifica il flag nell'elenco compose command:: --core.defaultRuleSyntax=v2. La modalità di compatibilità riguarda soltanto la sintassi delle regole. Non ripristina le opzioni rimosse e non rinomina automaticamente i middleware.
Passaggio 3: applica le rinomine dei middleware mentre sei ancora sulla v2.11. Cerca nei file Compose i nomi precedenti: grep -rn ipwhitelist docker-compose*.yml. Modifica ogni label ipwhitelist in ipallowlist e ricrea i servizi interessati con docker compose up -d. La v2.11 include già il middleware IPAllowList, quindi le label rinominate funzionano prima del passaggio, mentre l'avviso di deprecazione di IPWhiteList scompare dai log della v2. Le release precedenti alla v2.11 non riconoscono il nuovo nome; se nel passaggio 1 hai fissato una v2 precedente, passa prima a traefik:v2.11. (Se una vecchia label rimane, la v3 attuale riconosce ancora il nome precedente come alias deprecato, quindi l'elenco continua a essere applicato; correggilo nel passaggio successivo, non alle 2:00.)
Passaggio 4: modifica il tag dell'immagine. Imposta l'immagine Traefik sulla release v3 attuale, traefik:v3.7 alla data dell'11 ottobre 2026 (v3.7.14 è la patch più recente), quindi:
docker compose up -d
docker compose logs -f traefikPoiché la modalità di compatibilità è attiva, le regole v2 continuano a corrispondere. Inoltre, poiché le rinomine dei middleware sono già state applicate sulla v2.11, quei router vengono avviati correttamente. Un log in condizioni normali non contiene alcuna riga field not found né alcuna riga does not exist.
Considera con attenzione l'interruzione possibile durante questo passaggio. Un router che fa riferimento a un nome di middleware che la v3 non riconosce, ad esempio per un errore di battitura o un'opzione rimossa, non è operativo dal momento in cui viene avviata la nuova versione di Traefik fino alla correzione delle label e alla ricreazione del container dell'applicazione. Se una route non può rimanere inattiva nemmeno per un breve periodo, rimuovi il middleware sospetto dalla label middlewares del router prima del passaggio e aggiungilo nuovamente dopo. Decidi in anticipo se la route può funzionare senza quel middleware durante l'intervallo.
Passaggio 5: migra le regole servizio per servizio. Procedi un'applicazione alla volta: riscrivi la relativa regola nella sintassi v3, ricrea soltanto quel servizio con docker compose up -d app e testalo prima di continuare. Se un servizio contiene una regola che non puoi ancora riscrivere, assegna a quel singolo router la label di esclusione traefik.http.routers.app.ruleSyntax=v2 e continua.
Passaggio 6: disattiva la modalità di compatibilità. Quando tutte le regole usano la sintassi v3, elimina defaultRuleSyntax e tutte le label ruleSyntax, riavvia Traefik e verifica che ogni router continui a essere visualizzato in verde nella dashboard. Non mantenere la modalità di compatibilità attiva: Traefik ha deprecato entrambe le opzioni nella v3.4 e le rimuoverà nella prossima versione principale. Sono quindi un ponte temporaneo, non la configurazione definitiva.
Prima e dopo: le label di un servizio
Questa applicazione include contemporaneamente tutte le modifiche più comuni: un Host con più valori, un segnaposto PathPrefix e un middleware ipWhiteList. Il blocco 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=8080E lo stesso servizio migrato a 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=8080Sono cambiate due label. La regola ha suddiviso il suo Host con più valori in due matcher collegati da || e ha sostituito il segnaposto con PathRegexp; la label del middleware ha sostituito ipwhitelist con ipallowlist. L'entrypoint, il resolver dei certificati, il collegamento tra router e middleware e la porta del servizio non sono cambiati.
Testare ogni servizio con il dashboard
Dopo ogni modifica, aprire la pagina dei router HTTP nel dashboard. Ogni router dovrebbe essere verde. Un router con un badge di errore indica il problema esatto. Di solito si tratta di un middleware che non esiste con il nuovo nome oppure di una regola v3 che non può essere analizzata. Verificare quindi dall'esterno, un hostname alla volta:
curl -sI https://app.example.com/api/v1/statusUn 200 o il normale redirect dell'applicazione indica che routing e TLS funzionano ancora. Un 404 da Traefik indica che il router non è stato avviato. Tornare al dashboard e leggere l'errore. Lasciare docker compose logs -f traefik aperto in un secondo terminale durante il lavoro, perché ogni errore di analisi viene registrato lì non appena un container viene riavviato.
Rollback senza ambiguità
Conserva il file compose v2, la relativa configurazione statica e il backup acme.json finché tutti i servizi non saranno instradati su v3 e verificati in condizioni reali. Il rollback consiste nel ripristinare il commit precedente alla migrazione ed eseguire docker compose up -d. Deve essere ripristinato l'intero file, non soltanto il tag dell'immagine, perché la sintassi specifica di v3 non è valida in v2, esattamente come la sintassi di v2 non era valida in v3: un matcher PathRegexp non verrà analizzato correttamente. Le label ipallowlist rinominate sono compatibili con v2.11, ma non con le versioni v2 precedenti, che non riconoscono il nuovo nome. Se acme.json è stato perso o danneggiato durante la procedura, ripristina la copia di backup prima di avviare v2, così il rollback non consumerà il limite di richieste di Let's Encrypt riemettendo cinque certificati contemporaneamente.
FAQ
Devo riscrivere ogni regola del router per Traefik v3?
No. Una semplice regola Host(app.example.com) scritta con i backtick è valida in entrambe le versioni e copre la maggior parte delle configurazioni Compose. La riscrittura è necessaria solo quando una regola usa funzionalità disponibili esclusivamente in v2: espressioni regolari o segnaposto all'interno di Path e PathPrefix, più nomi host nella stessa Host() oppure i matcher rimossi Headers, HeadersRegexp e HostHeader.
Che cosa è successo a ipWhiteList in Traefik v3?
È stato rinominato in ipAllowList, mentre la configurazione interna è rimasta invariata. Pertanto, un'etichetta v2 come traefik.http.middlewares.office.ipwhitelist.sourcerange=10.0.0.0/24 diventa la stessa riga con ipallowlist al suo interno. v2.11 accetta già il nuovo nome, quindi puoi rinominarlo prima dell'aggiornamento. Le versioni v3 attuali, inclusa v3.7, accettano ancora il vecchio nome come alias deprecato. Un'etichetta non rinominata continua quindi ad applicare l'allowlist, producendo soltanto un avviso nel log. Considera questa compatibilità temporanea, non un motivo per rimandare la rinomina: i nomi deprecati possono essere rimossi in una versione successiva. Al contrario, un nome di middleware che Traefik non riconosce causa un errore immediato, con un errore del router e una risposta 404. La dashboard mostra l'errore e le richieste a quel nome host restituiscono 404.
Traefik v3 riesce ancora a leggere la sintassi delle regole v2?
Sì. Imposta core.defaultRuleSyntax: v2 nella configurazione statica per mantenere la sintassi v2 come impostazione predefinita durante la migrazione. Dopo aver ripristinato l'impostazione predefinita, usa l'etichetta per-router ruleSyntax=v2 per i singoli router ancora da convertire. Considera temporanee entrambe le impostazioni: Traefik le ha dichiarate deprecate in v3.4 e le rimuoverà nella versione principale successiva.
I certificati Let's Encrypt resteranno disponibili dopo l'aggiornamento?
Sì. Traefik v3 continua a leggere il file acme.json scritto da v2, quindi i certificati non vengono riemessi solo perché è cambiato il binario. Prima di iniziare, copia comunque il file in un luogo sicuro. Un rollback o un volume eliminato che causa la perdita di acme.json obbliga infatti a riemettere contemporaneamente tutti i certificati, mentre Let's Encrypt consente solo cinque certificati duplicati alla settimana per lo stesso insieme di nomi host.
Perché Traefik v3 non si avvia dopo l'aggiornamento?
Quasi sempre perché la configurazione statica contiene ancora un'opzione rimossa in v3. Traefik non si avvia quando trova opzioni che non riconosce. Per le opzioni residue note (pilot, providers.docker.swarmMode, experimental.http3 e tls.caOptional dei provider), il log indica la causa e quindi riporta incompatible deprecated install configuration option found (incompatible deprecated static option found in v3.4 e nelle versioni precedenti). Per qualsiasi opzione che v3 non ha mai riconosciuto, ad esempio un errore di battitura, riporta field not found insieme al nodo interessato. Elimina o sostituisci ogni opzione, quindi avvia nuovamente il container.