SSD Nodes Learn Hosting plans →
Guide Matt ConnorDi Matt Connor · Aggiornato 2026-08-27

Migrazione da Traefik v2 a v3: cosa cambia

Traefik v3 non si avvia con swarmMode o pilot nella configurazione statica. Risolvi l'errore "incompatible deprecated static option found" e 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.

Rinominazioni e rimozioni

  • ipWhiteList ora è ipAllowList, sia per il middleware HTTP sia per quello TCP. Le opzioni al suo interno non cambiano, quindi sourcerange mantiene esattamente lo stesso significato. Le versioni v3 attuali, inclusa la v3.5, accettano ancora il vecchio nome come alias deprecato e continuano ad applicare l'elenco, quindi questa singola rinominazione non interrompe il servizio al momento del passaggio. Rinominalo comunque: l'alias è destinato a essere rimosso e scompare dall'elenco delle funzionalità deprecate senza messaggi espliciti.
  • providers.docker.swarmMode=true è stato rimosso. Swarm dispone ora di un provider dedicato, configurato come providers.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 riga caOptional è sufficiente per completare la migrazione, perché l'indirizzo forwardAuth, gli header attendibili e l'outpost che li gestisce si comportano tutti 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, comprese le integrazioni Jaeger e Zipkin, sono stati rimossi e v3 esporta invece OTLP (il protocollo OpenTelemetry).
  • Le opzioni ssl* deprecate all'interno del middleware headers (sslRedirect, sslHost e le altre) sono state rimosse. I redirect dell'entrypoint e il middleware redirectScheme le hanno sostituite.

Queste rimozioni sono più importanti di quanto possa sembrare, perché Traefik rifiuta di avviarsi quando la configurazione statica contiene un'opzione che non riconosce. Una riga pilot o swarmMode rimasta nella configurazione arresta il container durante l'avvio con un messaggio incompatible deprecated static option found che indica l'elemento rimasto; un'opzione che Traefik non ha mai riconosciuto, come un refuso o tls.caOptional, causa invece un errore field not found. Pulisci la configurazione statica prima di modificare il tag dell'immagine.

Un nome di middleware che Traefik non riconosce realmente, per esempio un refuso o un nome rimosso anziché mantenuto come alias, produce un errore diverso: il router che lo utilizza viene caricato con un errore invece di 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 funzione. Tieni presente che ipwhitelist NON rientra in questa categoria nelle versioni v3 attuali: sopravvive come alias deprecato, quindi un label non rinominato continua a funzionare senza messaggi.

La sintassi delle regole cambia

Le regole consentono di eseguire le riscritture vere e proprie. In v3 cambiano i seguenti aspetti:

  • I valori all’interno dei matcher devono essere racchiusi tra backtick. v2 accettava anche le virgolette doppie; v3 non le accetta. Di conseguenza, Host("app.example.com") deve diventare Host(app.example.com).
  • PathPrefix non interpreta più le espressioni regolari né i segnaposto nello stile di {id}. Una regola v2 come PathPrefix(/api/{version:v[0-9]+}) deve diventare un matcher PathRegexp scritto usando la sintassi delle espressioni regolari Go.
  • I matcher ora accettano un solo valore. v2 consentiva Host(app.example.com,www.example.com); v3 richiede Host(app.example.com) || Host(www.example.com). Fanno eccezione Header, HeaderRegexp, Query e QueryRegexp, che accettano ancora un nome e un valore.
  • Headers e HeadersRegexp vengono rinominati rispettivamente in Header e HeaderRegexp.
  • HostHeader viene rimosso. In v3 usare Host, che esegue lo stesso tipo di corrispondenza.
  • Sono stati aggiunti due matcher: QueryRegexp e ClientIP, che consentono di verificare l’indirizzo del client all’interno di una regola.

La buona notizia è che una semplice regola Host(app.example.com) scritta con i backtick è già valida in v3. La maggior parte delle configurazioni Compose di piccole dimensioni usa esattamente questa sintassi. 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*.yml

Ogni 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-backup

Il percorso di migrazione

Passaggio 1: fissa ciò che esegui oggi. Modifica ogni tag traefik:latest o traefik:v2 impostandolo sulla 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 ricreare un singolo servizio con docker compose up -d <service> non è ancora un'operazione abituale, la guida alle basi di Docker Compose descrive le operazioni utilizzate in questa migrazione.

Passaggio 2: pulisci la configurazione statica e abilita la modalità di compatibilità. Rimuovi ogni opzione eliminata 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: v2

Oppure usa un 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: prepara la rinomina dei middleware. Cerca nei file Compose i nomi precedenti: grep -rn ipwhitelist docker-compose*.yml. Modifica ogni label ipwhitelist in ipallowlist, ma non applicare ancora la modifica, perché il nuovo nome non esiste nella v2. Queste modifiche devono essere applicate insieme all'attivazione descritta nel passaggio successivo. (Se un riferimento sfugge, la v3 attuale continua a riconoscere il nome precedente come alias deprecato, quindi l'elenco continua a essere applicato; correggilo nel passaggio successivo, non alle 2 di notte.)

Passaggio 4: modifica il tag dell'immagine. Imposta l'immagine Traefik sulla release v3 corrente, traefik:v3.5 al momento della stesura, quindi:

docker compose up -d
docker compose logs -f traefik

Poiché la modalità di compatibilità è attiva, le regole v2 continuano a funzionare. Inoltre, poiché up -d ha ricreato anche i servizi con le label dei middleware rinominati, i router si avviano correttamente. Un log in condizioni normali non contiene alcuna riga field not found né alcuna riga does not exist.

Valuta con attenzione la finestra operativa aperta da questo passaggio. Un router che fa riferimento a un nome di middleware che la v3 non riconosce realmente, a causa di un errore di battitura o di un'opzione rimossa, non è operativo dal momento in cui si avvia la nuova istanza di Traefik fino alla ricreazione del relativo container applicativo. Su un singolo host, questo richiede i pochi secondi necessari a docker compose up -d per elaborare l'elenco. Se una route non può subire nemmeno una breve interruzione, rimuovi il middleware rinominato dalla label middlewares di quel router prima dell'attivazione e aggiungilo nuovamente dopo. Decidi in anticipo se la route può rimanere senza il relativo elenco di indirizzi IP consentiti durante il minuto intermedio.

Passaggio 5: migra le regole servizio per servizio. Procedi un'applicazione alla volta: riscrivi la relativa regola usando la 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 deroga 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à più del necessario: Traefik ha dichiarato deprecate entrambe le opzioni nella v3.4 e le rimuoverà nella prossima versione principale. Sono quindi un passaggio temporaneo, non una 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=8080

E 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=8080

Sono 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/status

Un 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.

Onestà del rollback

Conserva il file Compose v2, la relativa configurazione statica e il backup acme.json fino a quando 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. È necessario ripristinare l'intero file, non soltanto il tag dell'immagine, perché le label specifiche di v3 non sono valide in v2, esattamente come le label di v2 non erano valide in v3: ipallowlist non esiste in v2 e neppure un matcher PathRegexp può essere analizzato in quella versione. Se acme.json è stato perso o danneggiato durante la procedura, ripristina la copia di backup prima di avviare v2. In questo modo il rollback non consumerà il limite di frequenza di Let's Encrypt richiedendo nuovamente 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 in un unico Host(), virgolette al posto dei backtick oppure i matcher rimossi Headers, HeadersRegexp e HostHeader.

Che cosa è successo a ipWhiteList in Traefik v3?

È stato rinominato in ipAllowList, senza modificare la configurazione interna. 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. Le versioni v3 attuali, inclusa la v3.5, accettano ancora il vecchio nome come alias deprecato. Un'etichetta non rinominata continua quindi ad applicare silenziosamente l'allowlist. Consideralo un periodo transitorio, non un motivo per evitare la rinomina: l'alias verrà rimosso e un nome di middleware che Traefik non riconosce realmente genera un errore esplicito, 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 predefinita durante la migrazione e usa l'etichetta ruleSyntax=v2 a livello di singolo router per le eccezioni rimanenti dopo aver ripristinato l'impostazione predefinita. Entrambe sono soluzioni temporanee: Traefik le ha deprecate nella v3.4 e le rimuoverà nella prossima versione principale.

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 emessi nuovamente solo perché è cambiato il binario. Copia comunque il file in un luogo sicuro prima di iniziare. Un rollback o un volume eliminato che perda acme.json obbliga a emettere nuovamente tutti i certificati contemporaneamente. Let's Encrypt consente infatti soltanto 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 rifiuta di avviarsi quando trova opzioni che non riconosce. Per le opzioni obsolete note (pilot, providers.docker.swarmMode, experimental.http3), il log riporta incompatible deprecated static option found e identifica la causa. Per qualsiasi opzione mai supportata da v3, come tls.caOptional, riporta field not found insieme al nodo. Elimina o sostituisci ogni opzione, quindi avvia nuovamente il container.