SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 已更新 2026-08-30

Traefik v2 升級 v3:哪些設定會失效?

Traefik v3 若在靜態設定中保留 swarmMode 或 pilot 將無法啟動,並顯示 "incompatible deprecated static option found"。本文說明修正方式與規則遷移。

Traefik v2 與 v3 有哪些變更

從 Traefik v2 遷移至 v3,主要是重新命名。其中最知名的變更,是將 ipWhiteList middleware 改名為 ipAllowList。除此之外,v3 也收緊 router 規則語法(PathPrefix 不再具備 regex 功能,部分 matchers 已重新命名或移除),並直接移除少數 providers 與選項。其餘設定仍可沿用:entrypoints、ACME 憑證設定、Docker labels 工作流程,以及您的 acme.json 都不受影響。v3 也提供相容模式,可繼續使用 v2 規則語法。因此,您可以先升級 binary,再逐一修改各服務的規則,而不必在同一個晚上一次完成,降低升級風險。

本指南假設您使用 Traefik reverse proxy 指南中的標籤式 Docker Compose 設定。該頁面以 v3 為基礎;本頁適用於仍在執行 traefik:v2 tag 的主機。

重新命名與移除項目

  • ipWhiteList 現在改為 ipAllowList,HTTP 與 TCP middleware 都適用。內部選項未變更,因此 sourcerange 的確切意義也不變。目前的 v3 發行版本(包括 v3.5)仍接受舊名稱作為已淘汰的別名,並持續套用該清單,因此這次重新命名不會在切換版本時導致服務中斷。不過仍應完成重新命名:該別名預定移除,而且會從淘汰清單中靜默消失,不會顯示明確提示。
  • providers.docker.swarmMode=true 已移除。Swarm 現在使用專用 provider,設定為 providers.swarm.endpoint
  • pilot 區段已完全移除。
  • experimental.http3 已移除。HTTP/3 直接在 entrypoint 上啟用。
  • tls.caOptional 已從 providers 與 forwardAuth middleware 中移除。如果該 middleware 前方是 自架的 Authentik SSO,刪除 caOptional 行就是完整的遷移步驟,因為 forwardAuth 位址、受信任標頭及其後方的 outpost 在 v3 中都維持相同運作方式。
  • InfluxDB v1 metrics provider、Rancher provider 與 Marathon provider 已移除。
  • Tracing 已移至 OpenTelemetry。專用的 tracing backend(包括 Jaeger 與 Zipkin 整合)已移除,v3 改為匯出 OTLP(OpenTelemetry protocol)。
  • headers middleware 中已淘汰的 ssl* 選項(sslRedirectsslHost 等)已移除。現在應使用 entrypoint redirection 與 redirectScheme middleware 取代。

這些移除項目的影響比表面上更大,因為 Traefik 的 static configuration 含有未知選項時會拒絕啟動。殘留的 pilotswarmMode 行會在容器啟動時停止容器,並顯示指明殘留項目的 incompatible deprecated static option found 訊息;Traefik 從未支援的選項(例如拼字錯誤或 tls.caOptional)則會改以 field not found 停止啟動。請先清理 static configuration,再修改 image tag。

Traefik 確實不認得的 middleware 名稱(例如拼字錯誤,或已移除而非設為別名的名稱)會以不同方式失敗:參照該名稱的 router 會以錯誤載入,而不是建立 route;dashboard 會標示該項目,API 則回報 middleware "offce@docker" does not exist。由於 router 從未啟動,對該 hostname 的請求會收到 404。請注意,在目前的 v3 中,ipwhitelist 不屬於此類別:它仍是已淘汰的別名,因此未重新命名的 label 仍可正常運作,不會顯示提示。

規則語法變更

規則是實際進行重新寫入的地方。v3 的變更如下:

  • matcher 內的值必須使用反引號。v2 也接受雙引號,但 v3 不接受,因此 Host("app.example.com") 必須改為 Host(app.example.com)
  • PathPrefix 不再理解正規表示式或 {id} 格式的預留位置。v2 的規則 PathPrefix(/api/{version:v[0-9]+}) 必須改為使用 Go 正規表示式語法撰寫的 PathRegexp matcher。
  • matcher 現在只接受單一值。v2 允許 Host(app.example.com,www.example.com);v3 則要求使用 Host(app.example.com) || Host(www.example.com)。例外是 HeaderHeaderRegexpQueryQueryRegexp,這些 matcher 仍接受名稱和值。
  • HeadersHeadersRegexp 重新命名為 HeaderHeaderRegexp
  • HostHeader 已移除。請改用 Host;它在 v3 中比對相同內容。
  • 新增兩個 matcher:QueryRegexp,以及用於在規則中比對用戶端位址的 ClientIP

好消息是:使用反引號撰寫的基本 Host(app.example.com) 規則已經符合 v3 語法。大多數小型 Compose 設定正是使用這種寫法,因此大多數 label 不需修改規則即可完成遷移。

開始前先稽核標籤

只要執行一次搜尋,就能估算遷移規模,因為每個不相容的標籤變更都會留下可由 grep 找到的模式:

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

每個命中結果都是需要修改的一行。ipwhitelist 變更為 ipallowlistHostHeader 變更為 HostHeaders 變更為 Header{...} 佔位符放在 PathPrefix 內時,會變更為 PathRegexp 比對器。Host() 內的逗號會變更為由 || 連接的兩個 Host() 比對器。若沒有命中結果,表示標籤已符合 v3 語法,遷移工作可縮減為靜態設定與映像標籤。若命中結果列滿整個畫面,也正適合重新評估這是否仍是這台主機的正確代理,而 Traefik 與 Nginx 和 Caddy 的比較 會將這項重寫成本,與另外兩者要求你為每個應用程式處理的工作放在一起衡量。

維持不變的部分

Entrypoint 及其 HTTP-to-HTTPS 重新導向、同時支援兩種 challenge type 的 ACME resolver、exposedByDefault、router 與 service label、loadbalancer.server.port,以及 dashboard,在 v3 中都與 v2 相同。憑證也會沿用,因為 v3 會繼續讀取 v2 寫入的 acme.json。不過,開始前仍應先備份該檔案,因為回復時若遺失檔案,就會直接觸發 Let's Encrypt 的重複憑證速率限制:

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

遷移路徑

Step 1:固定目前執行的版本。 將任何 traefik:latesttraefik:v2 標籤改為目前使用的確切版本,例如 traefik:v2.11,並將整個 compose 目錄提交至 git。之後每個步驟都能透過 checkout 還原。若你還不熟悉使用 docker compose up -d <service> 重新建立單一服務,Docker Compose 基礎指南涵蓋本次遷移所需的操作。

Step 2:清理靜態設定並啟用相容模式。 移除 v3 已捨棄的所有選項(pilotswarmModetls.caOptionalexperimental.http3),然後讓 v3 預設將規則視為 v2 語法。在 traefik.yml 中:

core:
  defaultRuleSyntax: v2

或者,在 compose command: 清單中以旗標設定:--core.defaultRuleSyntax=v2。相容模式只涵蓋規則語法。它不會恢復已移除的選項,也不會替你重新命名 middleware。

Step 3:準備 middleware 重新命名。 在 compose 檔案中搜尋舊名稱:grep -rn ipwhitelist docker-compose*.yml。將每個 ipwhitelist 標籤編輯為 ipallowlist,但先不要套用變更,因為 v2 中不存在新名稱。這些編輯會與下一步的切換一併套用。(若有遺漏,目前的 v3 仍會將舊名稱視為已棄用的別名,因此清單仍會持續套用;請在下一輪修正,不要拖到凌晨 2am。)

Step 4:切換 image 標籤。 將 Traefik image 設為目前的 v3 版本,本文撰寫時為 traefik:v3.5,然後執行:

docker compose up -d
docker compose logs -f traefik

由於已啟用相容模式,你的 v2 規則仍會比對成功;而且 up -d 也會重新建立 middleware 標籤已重新命名的服務,因此這些 router 能正常啟動。健康的日誌不會包含 field not found 行,也不會包含 does not exist 行。

請如實評估這個步驟會造成的服務中斷時段。若 router 參照了 v3 確實無法識別的 middleware 名稱(例如拼字錯誤或已移除的選項),從新的 Traefik 啟動起,直到重新建立其 app container 前都會停止運作。對單一主機而言,這段時間就是 docker compose up -d 處理清單所需的幾秒鐘。若某個路由確實不能中斷,請在切換前從該 router 的 middlewares 標籤移除已重新命名的 middleware,切換後再加回,並事先決定該路由是否能在中間這 1 分鐘不使用 IP allow list。

Step 5:逐一遷移規則。 一次處理一個 app:將其規則改寫為 v3 語法,使用 docker compose up -d app 只重新建立該服務,並在繼續之前測試。如果某個服務的規則暫時無法改寫,請為該單一 router 加上例外標籤 traefik.http.routers.app.ruleSyntax=v2,然後繼續處理其他服務。

Step 6:關閉相容模式。 所有規則都改為 v3 語法後,刪除 defaultRuleSyntax 及任何 ruleSyntax 標籤,重新啟動 Traefik,並確認儀表板中的每個 router 仍顯示綠色。不要長期開啟相容模式:Traefik 已在 v3.4 將這兩個選項標示為已棄用,並會在下一個 major version 移除它們。因此,相容模式是過渡方案,不是最終狀態。

前後對照:單一服務的標籤

以下是一個同時包含所有常見變更的應用程式:多值 HostPathPrefix 佔位符,以及 ipWhiteList 中介軟體。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

有 2 個標籤變更。規則將多值 Host 拆分為 2 個以 || 連接的比對器,並將佔位符替換為 PathRegexp;中介軟體標籤則將 ipwhitelist 替換為 ipallowlist。entrypoint、憑證解析器、路由器與中介軟體的連接,以及服務連接埠都未變更。

使用儀表板測試每項服務

每次切換後,開啟儀表板的 HTTP routers 頁面。每個 router 都應顯示綠色。帶有錯誤徽章的 router 會指出確切問題,通常是新名稱下不存在的 middleware,或是 rule v3 無法剖析。接著從外部逐一確認每個主機名稱:

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

出現 200 或應用程式通常會進行的重新導向,表示路由與 TLS 都正常運作。Traefik 回傳 404,表示 router 未成功啟動;請返回儀表板查看錯誤。作業期間,請在第二個終端機中持續開啟 docker compose logs -f traefik,因為每次容器重新啟動時,所有剖析失敗都會立即記錄在其中。

誠實面對回復

在所有服務都透過 v3 路由,且已實際運作驗證前,請保留 v2 compose 檔案、其靜態設定,以及 acme.json 備份。回復表示切換至遷移前的 commit,然後執行 docker compose up -d。必須回復整個檔案,不能只更換 image tag,因為 v3 專用的 label 在 v2 下同樣會出錯,就像 v2 的 label 在 v3 下會出錯一樣:v2 不存在 ipallowlist,而且 v2 也無法解析 PathRegexp matcher。如果 acme.json 在過程中遺失或損毀,請在啟動 v2 前先還原備份副本,避免回復時一次重新簽發 5 張憑證,耗用 Let's Encrypt 的 rate limit。

FAQ

我需要為 Traefik v3 重寫每一條路由規則嗎?

不需要。使用反引號撰寫的基本 Host(app.example.com) 規則,在兩個版本中都有效,足以涵蓋大多數 Compose 設定。只有在規則使用 v2 專屬功能時才需要重寫,例如在 PathPathPrefix 中使用 regex 或 placeholder、在單一 Host() 中指定多個主機名稱、使用引號而非反引號,或使用已移除的 HeadersHeadersRegexpHostHeader matcher。

Traefik v3 中的 ipWhiteList 發生了什麼變化?

它已重新命名為 ipAllowList,其中的設定保持不變。因此,像 traefik.http.middlewares.office.ipwhitelist.sourcerange=10.0.0.0/24 這樣的 v2 label,只需將其中的名稱改為 ipallowlist 即可。現行 v3 版本仍接受舊名稱作為已棄用的別名,包括 v3.5,因此未重新命名的 label 仍會在沒有明顯提示的情況下套用 allowlist。請將這視為暫時措施,不要因此跳過重新命名:該別名預定會移除,而 Traefik 完全不認得的 middleware 名稱則會立即失敗,並產生 router 錯誤及 404。dashboard 會顯示錯誤,傳送至該主機名稱的請求也會回傳 404。

Traefik v3 仍能讀取 v2 規則語法嗎?

可以。在靜態設定中設定 core.defaultRuleSyntax: v2,即可在遷移期間維持 v2 語法為預設值。切回預設值後,則可使用各 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 對相同主機名稱集合,每週只允許 5 張重複憑證。

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

幾乎總是因為靜態設定仍包含 v3 已移除的選項,而 Traefik 遇到不認得的選項時會拒絕啟動。對於常見的遺留選項(pilotproviders.docker.swarmModeexperimental.http3),log 會顯示 incompatible deprecated static option found 並指出問題項目;對於 v3 從未支援的項目,例如 tls.caOptional,則會顯示 field not found 及其節點。刪除或替換每一項後,再次啟動 container。