Traefik v2 升级 v3 迁移指南:配置变更与报错修复
Traefik v3 移除了 swarmMode 和 pilot 等配置,导致服务无法启动。本文详细解析 ipAllowList 迁移、HTTP/3 启用方式及弃用选项处理,助您快速修复配置错误并平滑升级至 v3 版本。
Traefik v2 和 v3 有哪些变化
从 Traefik v2 迁移到 v3 主要是重命名工作,最典型的变更是将 ipWhiteList 中间件重命名为 ipAllowList。除此之外,v3 收紧了路由规则语法(PathPrefix 不再支持正则表达式功能,部分匹配器已重命名或移除),并直接删除了部分 provider 和选项,但其他配置仍可继续使用:entrypoints、ACME 证书配置、Docker 标签工作流以及您的 acme.json 都可以沿用。v3 还提供兼容模式,可继续使用 v2 规则语法。这样您可以先升级二进制文件,再逐个服务重写规则,而不必在一个高风险的晚上一次性完成全部变更。
本指南假设您使用 Traefik 反向代理指南 中基于标签的 Docker Compose 配置。该页面采用 v3 原生配置;本指南适用于仍在运行 traefik:v2 标签的服务器。
重命名与移除项
ipWhiteList现已更名为ipAllowList,适用于 HTTP 和 TCP 中间件。内部选项保持不变,因此sourcerange的含义完全一致。当前的 v3 版本(包括 v3.7)仍将旧名称作为已弃用的别名处理,并继续强制执行列表,同时记录一条弃用警告。因此,此次重命名不会导致服务中断。建议尽快重命名:旧名称已被弃用,且 v2.11 已支持ipAllowList,因此可以在升级前完成此项更改。providers.docker.swarmMode=true已移除。Swarm 现拥有独立的提供程序,配置为providers.swarm.endpoint。pilot部分已完全移除。experimental.http3已移除。HTTP/3 现在直接在入口点(entrypoint)上启用。tls.caOptional已从提供程序和 forwardAuth 中间件中移除。如果该中间件位于 自托管 Authentik SSO 前端,删除caOptional行即完成了全部迁移工作,因为 forwardAuth 地址、受信任的标头以及其后的 outpost 在 v3 中的行为完全相同。- InfluxDB v1 指标提供程序、Rancher 提供程序以及 Marathon 提供程序均已移除。
- 追踪功能已迁移至 OpenTelemetry。专用的追踪后端(包括 Jaeger 和 Zipkin 集成)已移除,v3 改为导出 OTLP(OpenTelemetry 协议)。
- headers 中间件内已弃用的
ssl*选项(sslRedirect、sslHost及其他)已移除。入口点重定向和 redirectScheme 中间件已取代它们。
这些移除项的影响比预想中更大,因为如果静态配置中包含已移除或无法识别的选项,Traefik 将拒绝启动。残留的 pilot、swarmMode、experimental.http3 或提供程序 tls.caOptional 行会导致容器在启动时停止:Traefik 首先会记录一行指出残留项的日志(例如:Docker 提供程序 tls.CAOptional 选项已在 v3 中移除),随后以 incompatible deprecated install configuration option found 错误退出。v3.4 及之前的版本将该错误信息表述为 incompatible deprecated static option found。如果选项是 Traefik 从未识别的内容(例如拼写错误),它会以 field not found 和节点信息停止。在更改镜像标签之前,请务必清理静态配置。
如果中间件名称 Traefik 确实无法识别(拼写错误或已被移除而非重命名的名称),其表现会有所不同:引用该中间件的路由将无法加载,仪表板会标记该错误,API 会报告 middleware "offce@docker" does not exist。由于路由未成功启动,对该主机名的请求将返回 404。请注意,ipwhitelist 在当前的 v3 版本中不属于此类:它作为已弃用的别名保留了下来,因此未重命名的标签仍可正常工作。
规则语法变更
规则是实现实际重写的地方。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)。例外情况是Header、HeaderRegexp、Query和QueryRegexp,它们仍支持名称加值的格式。 Headers和HeadersRegexp已重命名为Header和HeaderRegexp。HostHeader已移除。请使用Host,它在 v3 中实现相同匹配功能。- 新增了两个匹配器:
PathRegexp和QueryRegexp。用于在规则内匹配客户端地址的ClientIP在 v2.11 中已存在,并保持不变。
好消息是:使用反引号编写的简单 Host(app.example.com) 规则在 v3 中已经是有效的语法。大多数小型 Compose 配置正是这样使用的,这意味着大多数标签无需修改规则即可迁移。
开始前审计标签
只需执行一次搜索,即可估算迁移规模,因为每个不兼容的标签变更都会留下可由 grep 查找的模式:
grep -rnE 'ipwhitelist|HostHeader|Headers\(|PathPrefix\(`[^`]*\{|Host\(`[^`]*`,' docker-compose*.yml每个匹配结果对应一行需要修改的配置。ipwhitelist 改为 ipallowlist。HostHeader 改为 Host。Headers 改为 Header。{...} 中的 PathPrefix 占位符改为 PathRegexp 匹配器。Host() 中的逗号改为两个由 || 连接的 Host() 匹配器。没有匹配结果,表示标签已经符合 v3 语法,迁移工作可缩减为静态配置和镜像标签。若匹配结果充满整个屏幕,也可以借此评估该代理是否仍适合这台主机;Traefik 与 Nginx 和 Caddy 的比较 会将这部分重写成本,与另外两者要求您为每个应用完成的工作进行对比。
保持不变的部分
入口点及其 HTTP 到 HTTPS 的重定向、支持两种质询类型的 ACME 解析器、exposedByDefault、路由器和服务标签、loadbalancer.server.port 以及仪表板,在 v3 中的工作方式与 v2 相同。证书也会继续保留,因为 v3 仍会读取 v2 写入的 acme.json。不过,开始前仍应备份该文件,因为回滚时如果丢失它,就会直接触发 Let's Encrypt 的重复证书速率限制:
cp ./letsencrypt/acme.json ./letsencrypt/acme.json.v2-backup迁移路径
第 1 步:锁定当前运行的版本。 将所有 traefik:latest 或 traefik:v2 标签更改为您当前使用的确切版本(例如 traefik:v2.11),并将整个 compose 目录提交到 git。后续的每一步操作都可以通过 checkout 回滚。如果您对使用 docker compose up -d <service> 重建单个服务还不熟悉,Docker Compose 基础指南 涵盖了本次迁移所依赖的操作。
第 2 步:清理静态配置并开启兼容模式。 移除 v3 版本中已废弃的所有选项(pilot、swarmMode、tls.caOptional、experimental.http3),然后告知 v3 默认将规则视为 v2 语法。在 traefik.yml 中配置:
core:
defaultRuleSyntax: v2或者作为 compose command: 列表中的一个标志:--core.defaultRuleSyntax=v2。兼容模式仅涵盖规则语法。它不会恢复已移除的选项,也不会为您重命名中间件。
第 3 步:在 v2.11 版本下应用中间件重命名。 在您的 compose 文件中搜索旧名称:grep -rn ipwhitelist docker-compose*.yml。将每个 ipwhitelist 标签编辑为 ipallowlist,并使用 docker compose up -d 重建这些服务。v2.11 版本已内置 IPAllowList 中间件,因此重命名后的标签在切换前即可生效,且 IPWhiteList 的弃用警告将从您的 v2 日志中消失。早于 v2.11 的版本无法识别新名称,因此如果您在第 1 步中锁定了更旧的 v2 版本,请先升级到 traefik:v2.11。(如果遗漏了一个,当前的 v3 版本仍会将旧名称作为弃用别名处理,因此列表会继续生效;请在后续工作中修复它,而不是在凌晨两点紧急处理。)
第 4 步:切换镜像标签。 将 Traefik 镜像设置为当前的 v3 版本,截至 2026 年 10 月 11 日为 traefik:v3.7(v3.7.14 是最新的补丁版本),然后执行:
docker compose up -d
docker compose logs -f traefik由于开启了兼容模式,您的 v2 规则将继续匹配;由于中间件重命名已在 v2.11 上生效,这些路由将正常启动。健康的日志中不应包含 field not found 行和 does not exist 行。
请客观评估此步骤带来的停机窗口。如果路由引用的中间件名称是 v3 无法识别的(例如拼写错误或已移除的选项),那么从新 Traefik 启动的那一刻起,该路由就会失效,直到您修复其标签并重建应用容器为止。如果某个路由确实不能中断,请在切换前从该路由的 middlewares 标签中移除可疑的中间件,并在切换后再重新添加;请提前决定该路由在切换期间是否可以暂时失去该中间件的功能。
第 5 步:逐个服务迁移规则。 一次处理一个应用:将其规则重写为 v3 语法,仅使用 docker compose up -d app 重建该服务,并在继续下一步之前进行测试。如果某个服务包含您暂时无法重写的规则,请为该路由添加逃生舱标签 traefik.http.routers.app.ruleSyntax=v2,然后继续进行其他迁移。
第 6 步:关闭兼容模式。 当所有规则都已转换为 v3 语法后,删除 defaultRuleSyntax 以及任何 ruleSyntax 标签,重启 Traefik,并确认仪表盘中所有路由的状态均为绿色。不要长期依赖兼容模式:Traefik 已在 v3.4 中弃用了这两个选项,并将在下一个主版本中移除它们,因此它们只是过渡方案,而非最终目标。
迁移前后:一个服务的标签
下面是一个一次性包含所有典型变更的应用:多值 Host、PathPrefix 占位符,以及 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有两个标签发生了变化。规则将多值 Host 拆分为两个由 || 连接的匹配器,并将占位符替换为 PathRegexp;中间件标签则将 ipwhitelist 替换为 ipallowlist。入口点、证书解析器、路由器到中间件的关联关系,以及服务端口均未改变。
使用控制面板测试每项服务
每次切换后,打开控制面板的 HTTP 路由页面。所有路由都应显示为绿色。带有错误标记的路由会指出具体问题。通常是中间件在更名后不存在,或规则 v3 无法解析。然后从外部逐个主机名确认:
curl -sI https://app.example.com/api/v1/status出现 200 或应用的正常重定向,表示路由和 TLS 均正常。Traefik 返回 404,表示路由未启动;返回控制面板并查看错误信息。操作期间,在第二个终端中保持 docker compose logs -f traefik 打开,因为每次容器重启时,所有解析失败都会立即记录在那里。
回滚的完整性
保留 v2 版本的 compose 文件、其静态配置以及 acme.json 备份,直到所有服务均已在 v3 版本上完成路由配置并经过实际验证。回滚意味着检出迁移前的提交并运行 docker compose up -d。回滚必须针对整个文件,而不仅仅是镜像标签,因为 v3 专有的语法在 v2 下会报错,正如 v2 语法在 v3 下不兼容一样:PathRegexp 匹配器无法在 v2 中解析。重命名后的 ipallowlist 标签在 v2.11 版本中可用,但在任何更早的 v2 版本中均无法识别。如果 acme.json 在过程中丢失或损坏,请在启动 v2 之前恢复备份副本,以避免回滚时因同时重新签发 5 个证书而耗尽 Let's Encrypt 的速率限制。
FAQ
我需要重写 Traefik v3 的所有路由规则吗?
不需要。使用反引号编写的普通 Host(app.example.com) 规则在两个版本中均有效,这涵盖了大多数 Compose 配置。仅当规则使用了 v2 独有功能时才需要重写:例如 Path 和 PathPrefix 内部的正则表达式或占位符、单个 Host() 内包含多个主机名,或者已移除的 Headers、HeadersRegexp 和 HostHeader 匹配器。
Traefik v3 中的 ipWhiteList 发生了什么变化?
它被重命名为 ipAllowList,内部配置保持不变,因此 v2 标签如 traefik.http.middlewares.office.ipwhitelist.sourcerange=10.0.0.0/24 只需将名称替换为 ipallowlist 即可。v2.11 已经支持新名称,因此您可以在升级前进行重命名。当前的 v3 版本(包括 v3.7)仍将旧名称作为弃用别名处理,因此未重命名的标签仍会强制执行白名单,仅会在日志中产生警告。请将其视为过渡期而非跳过重命名的理由:弃用的名称随时可能在后续版本中移除,而如果 Traefik 确实无法识别中间件名称,则会报错并导致路由失效,返回 404。仪表板会显示该错误,且对该主机名的请求将返回 404。
Traefik v3 还能读取 v2 规则语法吗?
可以。在静态配置中设置 core.defaultRuleSyntax: v2 可在迁移期间保持 v2 语法作为默认值,并在切换回默认值后,针对个别滞后的路由使用 ruleSyntax=v2 标签。请将两者视为临时方案:Traefik 已在 v3.4 中弃用它们,并将在下一个大版本中移除。
我的 Let's Encrypt 证书在升级后还能用吗?
可以。Traefik v3 会继续读取 v2 生成的 acme.json 文件,因此证书不会仅仅因为二进制文件变更而重新签发。无论如何,请在开始前将该文件备份到安全位置,因为回滚或删除卷导致 acme.json 丢失会强制所有证书同时重新签发,而 Let's Encrypt 对同一组主机名每周仅允许签发 5 次重复证书。
为什么 Traefik v3 在升级后无法启动?
通常是因为静态配置中仍包含 v3 已移除的选项,Traefik 会拒绝识别并启动。对于已知的残留项(pilot、providers.docker.swarmMode、experimental.http3 以及提供程序的 tls.caOptional),日志会指出具体条目并提示 incompatible deprecated install configuration option found(在 v3.4 及更早版本中为 incompatible deprecated static option found);对于 v3 从未识别的内容(如拼写错误),日志会提示 field not found 并指出节点位置。删除或替换这些条目,然后重新启动容器即可。