SSD Nodes Learn
指南 Matt Connor作者: Matt Connor · 已更新 2026-07-24

Traefik v2 升級 v3 哪些功能會失效?

遷移至 Traefik v3 時,若 static config 仍保留 swarmMode 或 pilot 設定將導致無法啟動。本文詳細列出 ipWhiteList 改名為 ipAllowList、移除舊版 providers 與 tracing 等重大變更,協助您順利完成版本升級。

Traefik v2 與 v3 的差異

從 Traefik v2 遷移至 v3 主要涉及重新命名作業,最顯著的變更為將 ipWhiteList middleware 重新命名為 ipAllowList。除此之外,v3 強化了 router rule 的語法(PathPrefix 不再支援 regex 功能,部分 matchers 已重新命名或移除),並直接刪除部分 providers 與 options;其餘功能皆可正常運作,包含 entrypoints、ACME 憑證設定、Docker labels 工作流,以及您的 acme.json 皆可直接沿用。v3 同時提供相容模式以支援 v2 的 rule 語法,因此您可以先升級 binary,再逐一重寫各個服務的 rules,避免一次性修改帶來風險。

本指南假設您使用 Traefik reverse proxy guide 中所提到的 label-based Docker Compose 設定。該頁面適用於 v3 版本;本頁則針對仍在使用 traefik:v2 tag 的環境。

重新命名與移除項目

  • HTTP 與 TCP middleware 中的 ipWhiteList 現已改名為 ipAllowList。內部選項保持不變,因此 sourcerange 的含義完全相同。目前的 v3 版本(包含 v3.5)仍接受舊名稱作為棄用別名(deprecated alias)並繼續執行該清單,因此此更名不會導致功能失效。但仍建議進行更名:該別名已排定移除,且會從棄用清單中靜默消失,不會發出警告。
  • providers.docker.swarmMode=true 已移除。Swarm 現在擁有專屬的 provider,並配置為 providers.swarm.endpoint
  • pilot 區段已完全移除。
  • experimental.http3 已移除。HTTP/3 現在直接在 entrypoint 啟用。
  • tls.caOptional 已從 providers 與 forwardAuth middleware 中移除。
  • 已移除 InfluxDB v1 metrics provider、Rancher provider 以及 Marathon provider。
  • Tracing 已遷移至 OpenTelemetry。原有的專用 tracing backends(包含 Jaeger 與 Zipkin 整合)已移除,v3 改為匯出 OTLP (OpenTelemetry protocol)。
  • headers middleware 中已移除棄用的 ssl* 選項(包含 sslRedirectsslHost 等)。現改由 entrypoint redirections 與 redirectScheme middleware 取代。

這些移除項目影響重大,因為若 static configuration 包含未知選項,Traefik 會拒絕啟動。若殘留 pilotswarmMode 行,容器會在啟動時停止,並顯示包含該殘留項目的 incompatible deprecated static option found 訊息;若選項是 Traefik 從未聽過的(例如打錯字或 tls.caOptional),則會顯示 field not found。在更換 image tag 前,請先清理 static configuration。

若 middleware 名稱是 Traefik 完全無法辨識的(例如打錯字,或該名稱已被移除而非僅設為別名),錯誤行為會有所不同:引用該名稱的 router 會載入錯誤而非路由,dashboard 會標記該錯誤,且 API 會回傳 middleware "offce@docker" does not exist。由於 router 無法正常啟動,發送到該 hostname 的請求會得到 404。請注意,在目前的 v3 版本中,ipwhitelist 並不屬於此類別:它仍作為棄用別名存在,因此未更名的 label 仍能正常運作。

規則語法變更

規則是執行重寫(rewriting)的核心。v3 的變更如下:

  • 匹配器(matcher)內的數值必須使用反引號(backticks)。v2 接受雙引號,但 v3 不支援,因此 Host("app.example.com") 必須改為 Host(app.example.com)
  • PathPrefix 不再支援正規表示式或 {id} 格式的佔位符。v2 的規則如 PathPrefix(/api/{version:v[0-9]+}) 必須改為使用 Go 正規表示法語法的 PathRegexp 匹配器。
  • 匹配器現在僅接受單一數值。v2 允許 Host(app.example.com,www.example.com);v3 則需改為 Host(app.example.com) || Host(www.example.com)。例外情況為 HeaderHeaderRegexpQueryQueryRegexp,這兩者仍需提供名稱與數值。
  • HeadersHeadersRegexp 已重新命名為 HeaderHeaderRegexp
  • HostHeader 已移除。請改用 Host,其在 v3 中匹配相同的內容。
  • 新增兩個匹配器:QueryRegexp,以及用於在規則中匹配用戶端位址的 ClientIP

好消息是:使用反引號撰寫的純 Host(app.example.com) 規則已符合 v3 語法。大多數小型 Compose 設定皆採用此格式,這代表大部分的標籤(labels)無需修改規則即可直接遷移。

開始前請先稽核您的 labels

您可以使用單次搜尋來估算遷移規模,因為每一次破壞性的 label 變更都會留下 grep 可搜尋的模式:

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

每一次匹配結果代表需要修改的一行。ipwhitelist 會變更為 ipallowlistHostHeader 會變更為 HostHeaders 會變更為 HeaderPathPrefix 內部的 {...} 佔位符會變更為 PathRegexp 匹配器。Host() 內的逗號會變更為由 || 連結的兩個 Host() 匹配器。若搜尋結果為零,代表您的 labels 已符合 v3 語法,遷移工作將縮減至僅需處理靜態配置與 image tag。

不變的部分

Entrypoints 及其 HTTP-to-HTTPS 重定向、包含兩種驗證類型 (challenge types) 的 ACME resolvers、exposedByDefault、router 與 service labels、loadbalancer.server.port 以及 dashboard,在 v3 中的運作方式與 v2 完全相同。憑證也會保留,因為 v3 會繼續讀取 v2 寫入的 acme.json。在開始之前,請務必備份該檔案;若回退 (rollback) 導致檔案遺失,會直接觸發 Let's Encrypt 的重複憑證 (duplicate-certificate) 速率限制:

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

遷移路徑

Step 1: 固定目前的執行版本。 將所有 traefik:latesttraefik:v2 標籤更改為您目前使用的確切版本(例如 traefik:v2.11),並將整個 compose 目錄 commit 至 git。之後的每個步驟都可以透過 checkout 進行復原。如果您尚未熟練使用 docker compose up -d <service> 重建單一服務,請參閱 Docker Compose basics guide,該指南涵蓋了本次遷移所依賴的操作。

Step 2: 清理靜態配置並開啟相容模式。 移除 v3 已廢棄的所有選項 (pilot, swarmMode, tls.caOptional, experimental.http3),然後設定 v3 預設將規則視為 v2 語法處理。在 traefik.yml 中:

core:
  defaultRuleSyntax: v2

或者作為 compose command: 列表中的 flag:--core.defaultRuleSyntax=v2。相容模式僅涵蓋規則語法。它不會復原已移除的選項,也不會為您重新命名 middlewares。

Step 3: 準備 middleware 重新命名。 在您的 compose 檔案中搜尋舊名稱:grep -rn ipwhitelist docker-compose*.yml。將每個 ipwhitelist 標籤修改為 ipallowlist,但請先不要套用變更,因為新名稱在 v2 中並不存在。這些修改將與下一步的切換同步進行。(若有遺漏,目前的 v3 仍會將舊名稱視為已廢棄的 alias 並予以支援,因此清單仍會持續強制執行;請在下次處理時修正,而非在凌晨 2 點處理。)

Step 4: 切換 image tag。 將 Traefik image 設定為目前的 v3 版本(撰寫本文時為 traefik:v3.5),然後:

docker compose up -d
docker compose logs -f traefik

由於已開啟相容模式,您的 v2 規則仍能正常匹配;且由於 up -d 也重建了您重新命名 middleware 標籤的服務,因此這些 routers 會正常啟動。健康的 log 不應包含 field not found 行與 does not exist 行。

請誠實評估此步驟產生的停機時間。若 router 引用了 v3 完全無法辨識的 middleware 名稱(例如打錯字或已移除的選項),該 router 會從新版 Traefik 啟動起,直到其 app container 被重建為止處於失效狀態;在單機環境下,這僅需 docker compose up -d 處理完清單所需的幾秒鐘。若某個 route 絕對不能中斷,請在切換前從該 router 的 middlewares 標籤中移除重新命名的 middleware,並在切換後重新加入,並預先決定該 route 是否能在這段間隙中暫時失去其 IP allow list。

Step 5: 逐一遷移服務規則。 每次處理一個 app:將其 rule 重寫為 v3 語法,僅使用 docker compose up -d app 重建該服務,並在繼續下一步前進行測試。若某個服務的 rule 目前無法重寫,請為該 router 加上 escape hatch 標籤 traefik.http.routers.app.ruleSyntax=v2 並繼續前進。

Step 6: 關閉相容模式。 當所有規則皆為 v3 語法時,刪除 defaultRuleSyntax 與任何 ruleSyntax 標籤,重啟 Traefik,並確認所有 router 在 dashboard 中仍顯示為綠色。請勿長期使用相容模式:Traefik 已在 v3.4 中將這兩個選項列為 deprecated,並將在下一個 major version 中移除它們,因此它們僅是過渡手段,而非最終目標。

變更前後:單一服務的 labels

此應用程式同時包含了幾項常見的變更:多值 HostPathPrefix 佔位符,以及 ipWhiteList middleware。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

同一個服務遷移至 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

共有兩處 labels 發生變更。規則將其多值 Host 拆分為兩個由 || 連接的匹配器,並將佔位符替換為 PathRegexp;此外,middleware label 將 ipwhitelist 替換為 ipallowlist。entrypoint、certificate resolver、router 與 middleware 的連接方式,以及 service port 皆未變動。

使用 Dashboard 測試各項服務

每次切換後,請開啟 Dashboard 的 HTTP routers 頁面。所有 router 應顯示為綠色。若 router 顯示錯誤標記,請查看其具體問題;通常是因為 middleware 在新名稱下不存在,或是 v3 無法解析該規則。接著,請逐一從外部確認各個 hostname:

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

若出現 200 或應用程式的正常重新導向,代表 routing 與 TLS 皆運作正常。若 Traefik 顯示 404,代表 router 未成功啟動;請返回 Dashboard 查看錯誤訊息。操作期間請在第二個終端機保持 docker compose logs -f traefik 開啟,因為容器重啟時,所有的解析錯誤都會立即顯示於此。

回滾準則

在所有服務都已切換至 v3 並完成實際測試前,請保留 v2 的 compose file、靜態配置以及 acme.json 備份。回滾時,必須切換回遷移前的 commit 並執行 docker compose up -d。回滾必須針對整個檔案進行,而不僅僅是更改 image tag;因為 v3 專用的 labels 在 v2 環境下會出錯,其錯誤性質與 v2 labels 在 v3 環境下的錯誤完全相同:v2 並不支援 ipallowlist,且 PathRegexp 匹配器在該版本也無法解析。若 acme.json 在過程中遺失或損毀,請在啟動 v2 前先還原備份,以避免回滾過程因同時重新核發五張憑證而耗盡 Let's Encrypt 的 rate limit。

FAQ

我必須為 Traefik v3 重寫所有的 router rule 嗎?

不需要。使用 backticks 撰寫的單純 Host(app.example.com) rule 在兩個版本中皆有效,這已涵蓋大部分的 Compose 設定。只有當 rule 使用了 v2 專用的功能時才需要重寫:例如在 PathPathPrefix 內使用 regex 或 placeholders、在單一 Host() 內使用多個 hostnames、使用 quotes 而非 backticks,或是使用了已被移除的 HeadersHeadersRegexpHostHeader matchers。

Traefik v3 中的 ipWhiteList 變更為何?

它已重新命名為 ipAllowList,但內部的配置內容不變。因此,原本的 v2 label(如 traefik.http.middlewares.office.ipwhitelist.sourcerange=10.0.0.0/24)會變成包含 ipallowlist 的相同行。目前的 v3 版本(包含 v3.5)仍接受舊名稱作為棄用的 alias,因此未更名的 label 仍會靜默執行 allowlist。請將此視為暫時的緩衝期而非不需更名的理由:該 alias 已排定移除,若使用 Traefik 完全無法辨識的 middleware 名稱,會導致 router error 並回傳 404。Dashboard 會顯示該錯誤,且對該 hostname 的請求會回傳 404。

Traefik v3 還能讀取 v2 的 rule syntax 嗎?

可以。在靜態配置中設定 core.defaultRuleSyntax: v2,即可在遷移期間將 v2 syntax 保持為預設值;待切換回預設值後,可針對個別尚未轉換的項目使用 per-router ruleSyntax=v2 label。請將兩者皆視為暫時方案:Traefik 已在 v3.4 中將其棄用,並將在下一個 major version 中移除。

我的 Let's Encrypt 憑證在升級後會保留嗎?

會。Traefik v3 會繼續讀取 v2 寫入的 acme.json 檔案,因此不會僅因 binary 變更就重新核發憑證。儘管如此,在開始前仍請將檔案備份至安全位置,因為若發生 rollback 或刪除 volume 導致 acme.json 遺失,會強制同時重新核發所有憑證;而 Let's Encrypt 對於相同 hostnames 的重複憑證,每週僅允許核發 5 次。

為什麼升級後 Traefik v3 無法啟動?

幾乎都是因為靜態配置中仍包含 v3 已移除的選項,而 Traefik 無法在含有未知選項的情況下啟動。若為常見的殘留項(pilotproviders.docker.swarmModeexperimental.http3),日誌會顯示 incompatible deprecated static option found 並指出錯誤原因;若為 v3 從未聽過的選項(例如 tls.caOptional),則會顯示 field not found 並標示該節點。請刪除或替換每個錯誤選項,然後重新啟動 container。