为什么Traefik在后端网络上发现容器IP地址?

时间:2020-10-29 14:02:32

标签: docker docker-compose traefik

我使用Traefik basic example并提供两项服务:traefik本身和traefik/whoami,我将两种服务分别分配给名为web的网络,后者分配给backend网络好吧。

但是,Traefik发现了backend服务的traefik/whoami IP地址,无法通过web网络建立联系,并导致“网关超时”

为了强迫Traefik使用网络,我同时添加了--providers.docker.network=webtraefik.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网络时,它工作正常!

1 个答案:

答案 0 :(得分:1)

网络名称有一个小故障。当您在撰写文件中运行并且不引用外部网络时,网络名称将在当前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:通过环境修复并引用项目名称

相应地构造网络名称,以使参数与docker-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项目名称(或相应地设置env)

COMPOSE_PROJECT_NAME=proj docker-compose up

问题是您确实需要为每个调用指定该变量。您可以通过使用.env旁边的docker-compose.yml文件来解决此问题。

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网络标签,因为您无需覆盖默认值。

此设置还允许使用容器(也应从此traefik实例公开)来启动其他组合项目。所以我会选择第二种选择...