如何配置Traefik拦截Docker容器间的流量?
本地开发环境用Traefik v2.8做反向代理,通过docker-compose管理服务。已在主机/etc/hosts配置host.docker.internal指向127.0.0.1和localhost:
127.0.0.1 host.docker.internal localhost host.docker.internal
服务映射关系:
host.docker.internal:8443对应service_ahost.docker.internal:8453对应service_b
Traefik已配置路由a.localhost指向host.docker.internal:8443,主机外部访问a.localhost正常,但service_b容器内访问该域名时,先出现unknown host错误;尝试在主机/etc/hosts添加a.localhost映射后,又出现connection refused错误。
现有配置
docker-compose.yml片段
version: '3' services: reverse_proxy: image: traefik:v2.8 # Enables the web UI and tells Traefik to listen to docker command: --api.insecure=true --providers.docker ports: - "80:80" - "443:443" # The Web UI (enabled by --api.insecure=true) - "9000:8080" volumes: # So that Traefik can listen to the Docker events - /var/run/docker.sock:/var/run/docker.sock - ./dev-traefik/traefik.yml:/etc/traefik/traefik.yml - ./dev-traefik:/configurations service_a: ports: - "8443:8443" service_b: ports: - "8453:8453"
Traefik dynamic-config.yml
http: routers: service-a-router: service: service-a rule: "Host(`a.localhost`)" tls: "true" # using tls services: service-a: loadBalancer: servers: - url: "https://host.docker.internal:8443" # service A tls: certificates: - certFile: "/etc/https/tls.crt" keyFile: "/etc/https/tls.key" stores: default: defaultCertificate: certFile: "/etc/https/tls.crt" keyFile: "/etc/https/tls.key"
1. 解决容器内a.localhost的DNS解析问题
容器内部无法读取主机的/etc/hosts配置,所以service_b无法识别a.localhost的IP,两种可行方案:
- 方案一:用extra_hosts直接映射
在service_b的docker-compose配置中添加extra_hosts,将a.localhost指向主机网关(Docker 20.10+支持host-gateway变量,自动指向主机网关IP):
service_b: ports: - "8453:8453" extra_hosts: - "a.localhost:host-gateway"
若Docker版本较低,直接替换为主机的局域网IP(如192.168.3.10)即可。
- 方案二:自定义Docker网络+服务名映射
创建自定义Docker网络,让所有服务加入同一网络,然后将a.localhost指向Traefik的服务名reverse_proxy,让请求直接发送到Traefik容器:
修改docker-compose.yml,添加自定义网络并配置所有服务加入该网络:
version: '3' networks: app-network: driver: bridge services: reverse_proxy: image: traefik:v2.8 command: --api.insecure=true --providers.docker --providers.docker.network=app-network ports: - "80:80" - "443:443" - "9000:8080" volumes: - /var/run/docker.sock:/var/run/docker.sock - ./dev-traefik/traefik.yml:/etc/traefik/traefik.yml - ./dev-traefik:/configurations networks: - app-network service_a: ports: - "8443:8443" networks: - app-network service_b: ports: - "8453:8453" networks: - app-network extra_hosts: - "a.localhost:reverse_proxy"
2. 优化Traefik路由,贴近云端部署逻辑
当前配置中Traefik通过主机端口访问service_a,在Docker网络内完全没必要——直接用服务内部名称和端口访问,更符合云端服务发现的逻辑:
修改dynamic-config.yml的service配置:
http: routers: service-a-router: service: service-a rule: "Host(`a.localhost`)" tls: "true" services: service-a: loadBalancer: servers: - url: "https://service_a:8443" # 直接用service_a的服务名访问容器内部端口
注意:service_a的服务必须监听在容器的0.0.0.0:8443上,不能仅监听127.0.0.1,否则Traefik无法建立连接。
3. 处理自签名证书问题
如果使用自签名证书,service_b容器内的curl会因为证书不被信任报错。开发环境可以临时使用curl --insecure https://a.localhost跳过验证,或者将自签名证书导入service_b的容器信任列表中。
内容的提问来源于stack exchange,提问作者Laurenzo

