为什么 Traefik 在后端网络上发现容器 IP 地址?
Why Traefik discovers container IP address on backend network?
使用 Traefik basic example 和 2 项服务:traefik
本身和 traefik/whoami
,我将这两项服务分配给名为 web
的网络,后者分配给 backend
网络也是如此。
但是,Traefik 发现 traefik/whoami
服务的 backend
IP 地址,无法通过 web
网络进行联系,导致“网关超时”
为了强制 Traefik 使用 web 网络,我也添加了 --providers.docker.network=web
和 traefik.docker.network=web
,但它仍然发现 backend
IP 地址。
如何让 Traefik 在正确的网络上发现服务 IP 地址?
这是我要开始工作的 docker-compose.yml
文件。
version: "3.8"
services:
traefik:
image: "traefik:v2.3"
command:
- --log.level=DEBUG
- --api.insecure=true
- --api.dashboard=true
- --api.debug=true
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
- --providers.docker.network=web
ports:
- "80:80"
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
- web
whoami:
image: "traefik/whoami"
labels:
- traefik.enable=true
- traefik.http.routers.whoami.rule=Host(`whoami.localhost`)
- traefik.http.routers.whoami.entrypoints=web
- traefik.docker.network=web
networks:
- web
- backend
networks:
web:
backend:
PS! 当您从服务中删除 backend
网络时,它工作正常!
网络名称存在一个小问题。由于您 运行 在撰写文件中并且不引用外部网络,因此网络名称是在当前 compose project
的范围内创建的。启动时,您可能会看到一些消息说
Creating network "traefik2-test_web" with the default driver
Creating network "traefik2-test_backend" with the default driver
(假设您 运行 所在的文件夹名为 traefik2-test)这意味着创建的 docker 网络以项目名称为前缀,例如允许为独立实例旋转撰写文件两次。
您可能还会在日志中看到一些错误,表明未找到名为 web
的已配置网络 - 因此它回退到随机选择一个网络。
traefik_1 | time="2020-10-29T14:24:25Z" level=warning msg="Could not find network named 'web' for container '/traefik2-test_whoami_1'! Maybe you're missing the project's prefix in the label? Defaulting to first available network." providerName=docker container=whoami-traefik2-test-4661d09157cf941b7efd7c8154af5611249866c4bc394c256e225e05db21a784 serviceName=whoami-traefik2-test
所以 traefik 需要网络的全局有效名称,而不关心它是从 compose 项目内部启动的。您可以通过执行
来验证网络名称
docker container inspect XXX_whoami_1
其中 XXX 是您的 docker-compose 项目的名称。
你现在可以做什么?
解决方案 1:修复并通过 env 引用项目名称
相应地构造网络名称,以便参数与 docker-compose 创建的网络的全局唯一名称相匹配。如果您在这个 compose 文件中的所有目标容器都在 web
网络中,您甚至可以省略目标容器上的特殊标签。
traefik:
image: "traefik:v2.3"
command:
- --log.level=DEBUG
- --api.insecure=true
- --api.dashboard=true
- --api.debug=true
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
- --providers.docker.network=${COMPOSE_PROJECT_NAME}_web
ports:
- "80:80"
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
- web
这需要您为每个命令传递一个 docker 组合项目名称(或相应地设置环境)
COMPOSE_PROJECT_NAME=proj docker-compose up
问题在于您确实需要为每次调用指定该变量。您可以通过在启用该功能的 docker-compose.yml
旁边使用 .env
文件来解决该问题。
COMPOSE_PROJECT_NAME=projfromenv
备选方案:外网参考
但可能有更好的解决方案。第二种选择是通过引用现有网络来使用全球唯一的网络名称。这需要像这样初始设置网络:
docker network create traefik-net
然后在网络部分引用它:
networks:
web:
external: true
name: traefik-net
backend:
并使用此网络名称(片段)的引用启动 traefik:
- --providers.docker.network=traefik-net
您的目标容器仍然引用本地网络名称 web
,该名称现在是对该全局网络的引用。您不需要为 whoami 容器指定 traefik 网络标签,因为您不需要覆盖默认值。
此设置还允许使用容器启动其他 compose 项目,这些容器也应该从此 traefik 实例中公开。所以我会选择第二个选项...
使用 Traefik basic example 和 2 项服务:traefik
本身和 traefik/whoami
,我将这两项服务分配给名为 web
的网络,后者分配给 backend
网络也是如此。
但是,Traefik 发现 traefik/whoami
服务的 backend
IP 地址,无法通过 web
网络进行联系,导致“网关超时”
为了强制 Traefik 使用 web 网络,我也添加了 --providers.docker.network=web
和 traefik.docker.network=web
,但它仍然发现 backend
IP 地址。
如何让 Traefik 在正确的网络上发现服务 IP 地址?
这是我要开始工作的 docker-compose.yml
文件。
version: "3.8"
services:
traefik:
image: "traefik:v2.3"
command:
- --log.level=DEBUG
- --api.insecure=true
- --api.dashboard=true
- --api.debug=true
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
- --providers.docker.network=web
ports:
- "80:80"
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
- web
whoami:
image: "traefik/whoami"
labels:
- traefik.enable=true
- traefik.http.routers.whoami.rule=Host(`whoami.localhost`)
- traefik.http.routers.whoami.entrypoints=web
- traefik.docker.network=web
networks:
- web
- backend
networks:
web:
backend:
PS! 当您从服务中删除 backend
网络时,它工作正常!
网络名称存在一个小问题。由于您 运行 在撰写文件中并且不引用外部网络,因此网络名称是在当前 compose project
的范围内创建的。启动时,您可能会看到一些消息说
Creating network "traefik2-test_web" with the default driver
Creating network "traefik2-test_backend" with the default driver
(假设您 运行 所在的文件夹名为 traefik2-test)这意味着创建的 docker 网络以项目名称为前缀,例如允许为独立实例旋转撰写文件两次。
您可能还会在日志中看到一些错误,表明未找到名为 web
的已配置网络 - 因此它回退到随机选择一个网络。
traefik_1 | time="2020-10-29T14:24:25Z" level=warning msg="Could not find network named 'web' for container '/traefik2-test_whoami_1'! Maybe you're missing the project's prefix in the label? Defaulting to first available network." providerName=docker container=whoami-traefik2-test-4661d09157cf941b7efd7c8154af5611249866c4bc394c256e225e05db21a784 serviceName=whoami-traefik2-test
所以 traefik 需要网络的全局有效名称,而不关心它是从 compose 项目内部启动的。您可以通过执行
来验证网络名称docker container inspect XXX_whoami_1
其中 XXX 是您的 docker-compose 项目的名称。
你现在可以做什么?
解决方案 1:修复并通过 env 引用项目名称
相应地构造网络名称,以便参数与 docker-compose 创建的网络的全局唯一名称相匹配。如果您在这个 compose 文件中的所有目标容器都在 web
网络中,您甚至可以省略目标容器上的特殊标签。
traefik:
image: "traefik:v2.3"
command:
- --log.level=DEBUG
- --api.insecure=true
- --api.dashboard=true
- --api.debug=true
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
- --providers.docker.network=${COMPOSE_PROJECT_NAME}_web
ports:
- "80:80"
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
- web
这需要您为每个命令传递一个 docker 组合项目名称(或相应地设置环境)
COMPOSE_PROJECT_NAME=proj docker-compose up
问题在于您确实需要为每次调用指定该变量。您可以通过在启用该功能的 docker-compose.yml
旁边使用 .env
文件来解决该问题。
COMPOSE_PROJECT_NAME=projfromenv
备选方案:外网参考
但可能有更好的解决方案。第二种选择是通过引用现有网络来使用全球唯一的网络名称。这需要像这样初始设置网络:
docker network create traefik-net
然后在网络部分引用它:
networks:
web:
external: true
name: traefik-net
backend:
并使用此网络名称(片段)的引用启动 traefik:
- --providers.docker.network=traefik-net
您的目标容器仍然引用本地网络名称 web
,该名称现在是对该全局网络的引用。您不需要为 whoami 容器指定 traefik 网络标签,因为您不需要覆盖默认值。
此设置还允许使用容器启动其他 compose 项目,这些容器也应该从此 traefik 实例中公开。所以我会选择第二个选项...