Traefik 是一个很好用的反向代理服务器,它可以自动发现 Docker 容器中的服务,然后进行反向代理(不再需要手动指定映射到宿主机端口再去配置代理服务器),并且还可以自动申请 TLS 证书,自动提供 HTTP2 服务。十分爽。
但一旦 Traefik 和多个 network 的服务一起工作,它就会随机的出问题,没错,随机的出问题,所以别问你为什么没这个问题,是你运气好。
version: "3.7"
services:
django:
build:
context: .
dockerfile: Dockerfile
restart: always
labels:
- "traefik.enable=false"
nginx:
build:
context: .
dockerfile: ./docker/nginx/Dockerfile
restart: always
networks:
- default
- traefik
depends_on:
- "django"
labels:
- "traefik.enable=true"
- "traefik.http.routers.name.rule=Host(`...`)"
- "traefik.http.routers.name.entrypoints=websecure"
- "traefik.http.routers.name.tls=true"
- "traefik.http.routers.name.tls.certresolver=tls"
networks:
traefik:
name: traefik
external: true
如上是一个很简单朴素的 docker-compose.yml
文件,当同一台服务器上出现两个或两个以上一摸一样的配置(名字不同)时,问题就出来了。Traefik 将在你每次重新启动项目之后,随机的在多个 network 之间选择一个,并且往往是错的一个。
问题的具体表示就是你在浏览器里访问服务时,会出现 Gateway Timeout
的文字提示。但在服务器使用 curl
访问通过查看 Traefik 给的面板里看到的内网 IP 地址,却又可以正常访问到服务。
在我浪费了人生的八小时之后,成功从一个 Github Issue 里找到了这个问题的答案——在labels
里增加一行 - "traefik.docker.network=traefik"
,这会告诉 Traefik 你别瞎找了,直接从名为 traefik
的 network 里找 IP 地址就行。
注意:以上未申明 Traefik 版本均为当前最新的 v2 版本。