如何实现Traefik级联部署:跨Docker子网路由独立服务
这个架构我之前帮朋友搭建过,核心就是解决Docker网络互通+Traefik跨实例路由的问题,分几步就能搞定:
1. 先搞定Docker网络互通(最关键的一步)
每个Docker Compose默认会创建孤立的内部网络,所以要让traefik_main能访问到traefik_a和traefik_b,最简单的方式是创建一个共享的外部网络,让三个Compose都加入这个网络。
创建共享网络
先在主机上手动创建一个外部网络:
docker network create traefik_shared
给每个Compose配置加入共享网络
traefik_main的docker-compose.yml片段:
networks: traefik_shared: external: true # 指定这是外部创建的网络 traefik_main_internal: # 这个是traefik_main自己的内部服务网络,和共享网络隔离 driver: bridge services: traefik-main: image: traefik:v2.10 # 其他配置... networks: - traefik_shared - traefik_main_internal
traefik_a的docker-compose.yml片段(traefik_b同理):
networks: traefik_shared: external: true traefik_a_internal: # 自己的内部服务网络,比如service1.a.com就在这个网络里 driver: bridge services: traefik-a: image: traefik:v2.10 # 其他配置... networks: - traefik_shared - traefik_a_internal
这样三个Traefik实例就处于同一个共享网络里,Docker的内置DNS会自动解析服务名(比如traefik-a、traefik-b)到对应容器的IP,不用手动写IP。
2. 配置traefik_a和traefik_b的入口
traefik_a和traefik_b不需要暴露端口到主机(除非你要绕过traefik_main直接访问),只要在共享网络里开放它们的Web入口端口(默认是80)就行。比如traefik-a的启动命令可以这样写:
services: traefik-a: command: - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:80" # 在容器内监听80端口,共享网络里能访问 volumes: - /var/run/docker.sock:/var/run/docker.sock:ro # 不要加ports字段暴露到主机,保持内部访问即可
3. 配置traefik_main的路由规则
接下来要让traefik_main根据域名后缀把请求转发到对应的子Traefik实例,推荐用File Provider来配置动态路由,比Docker Provider更清晰。
给traefik_main添加File Provider配置
首先在traefik_main的配置目录下创建dynamic_conf.yml:
http: routers: # 匹配所有*.a.com的域名,转发到traefik-a route-to-a: rule: "HostRegexp(`{subdomain:[a-z0-9-]+}.a.com`)" entryPoints: - web # 对应traefik_main的入口点 service: traefik-a-service # 匹配所有*.b.com的域名,转发到traefik-b route-to-b: rule: "HostRegexp(`{subdomain:[a-z0-9-]+}.b.com`)" entryPoints: - web service: traefik-b-service services: traefik-a-service: loadBalancer: servers: - url: "http://traefik-a:80" # 用共享网络里的服务名访问traefik-a的80端口 traefik-b-service: loadBalancer: servers: - url: "http://traefik-b:80"
然后在traefik_main的启动命令里加载这个动态配置:
services: traefik-main: command: - "--api.insecure=true" # 调试用,生产环境一定要关掉 - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:80" - "--providers.file.directory=/etc/traefik/dynamic" # 指定动态配置目录 volumes: - ./dynamic:/etc/traefik/dynamic # 挂载刚才创建的dynamic_conf.yml目录 - /var/run/docker.sock:/var/run/docker.sock:ro
4. 验证配置
启动三个Compose后:
- 访问
service1.a.com,traefik_main会把请求转发到traefik-a,再由traefik-a路由到对应的service1服务。 - 可以用
docker exec traefik-main-container curl http://traefik-a:80测试连通性,看能不能正常访问traefik-a的入口。
额外注意事项
- 生产环境一定要开启HTTPS,
traefik_main可以统一管理所有域名的TLS证书,子Traefik实例只要处理HTTP请求就行。 - 如果用Traefik v3,配置语法略有差异,但核心的网络互通和路由转发逻辑完全一致。
- 要是不想用共享网络,也可以把
traefik_a和traefik_b的网络设置为external: true让traefik_main直接连接,但共享网络的方式更干净。
内容的提问来源于stack exchange,提问作者Thomas




