在单域名下用Traefik Docker部署多服务出现路由错误
问题原因
Traefik 匹配路由时,若多个规则都能命中同一请求,会依据路由优先级(默认由规则特异性决定,也可手动设置)选择最终路由。你的 interface 服务路由仅匹配域名,而 api_server 路由是域名+PathPrefix(/api)——理论上后者优先级更高,但实际因规则解析或默认优先级计算问题,导致 interface 路由先被匹配,/api 请求被错误转发到 interface 服务,引发404。
解决办法
有两种方式可以修复这个问题:
方法一:给API路由设置更高优先级
在 api_server 的标签中添加优先级配置,确保其规则优先被匹配:
api_server: labels: - "traefik.enable=true" - "traefik.http.routers.api.rule=Host(`${DOMAIN}`) && PathPrefix(`/api`)" - "traefik.http.routers.api.entrypoints=websecure" - "traefik.http.routers.api.tls.certresolver=my-resolver" - "traefik.http.services.api.loadbalancer.server.port=8000" - "traefik.http.routers.api.service=api" - "traefik.http.routers.api.middlewares=api_strip" - "traefik.http.middlewares.api_strip.stripprefix.prefixes=/api" - "traefik.http.middlewares.api_strip.stripprefix.forceslash=false" # 添加优先级配置 - "traefik.http.routers.api.priority=10"
可选:给 interface 路由设置更低优先级,进一步明确匹配顺序:
interface: labels: - "traefik.enable=true" - "traefik.http.routers.interface.rule=Host(`${DOMAIN}`)" - "traefik.http.routers.interface.entrypoints=websecure" - "traefik.http.routers.interface.tls.certresolver=my-resolver" - "traefik.http.services.interface.loadbalancer.server.port=80" # 添加优先级配置 - "traefik.http.routers.interface.priority=0"
方法二:修改interface路由规则,排除/api路径
直接让 interface 路由不匹配任何 /api 开头的请求,从根源避免冲突:
interface: labels: - "traefik.enable=true" # 修改rule标签,排除/api路径 - "traefik.http.routers.interface.rule=Host(`${DOMAIN}`) && !PathPrefix(`/api`)" - "traefik.http.routers.interface.entrypoints=websecure" - "traefik.http.routers.interface.tls.certresolver=my-resolver" - "traefik.http.services.interface.loadbalancer.server.port=80"
额外验证步骤
- 确认
api_server容器内的服务正常监听8000端口,可通过docker exec <api容器ID> curl localhost:8000/api测试服务可用性 - 访问Traefik dashboard(默认8080端口),查看已加载的路由规则,确认API路由的规则和优先级配置正确生效
内容的提问来源于stack exchange,提问作者Mastermind
相关产品推荐
相关产品推荐

