【问题标题】:Traefik > "Bad gateway" (error 502) for some containersTraefik > 某些容器的“Bad gateway”(错误 502)
【发布时间】:2018-03-21 23:00:50
【问题描述】:

我在使用 traefik 和 docker 时遇到了一些问题,我不知道为什么。

对于某些容器,它就像一个魅力,而对于其他容器,当我尝试访问这些容器时出现错误:网关错误(错误 502)。

这是我的 traefik.toml :

# Service logs (here debug mode)
debug = true
logLevel = "DEBUG"

defaultEntryPoints = ["http", "https"]

# Access log
filePath = "/var/log/traefik/access.log"
format = "common"

################################################################
# Web configuration backend
################################################################
[web]
address = ":8080"

################################################################
# Entry-points configuration
################################################################
[entryPoints]
  [entryPoints.http]
    address = ":80"
    [entryPoints.http.redirect]
      entryPoint = "https"
  [entryPoints.https]
    address = ":443"
    [entryPoints.https.tls]

################################################################
# Docker configuration backend
################################################################
[docker]
domain = "domain.tld"
watch = true
exposedbydefault = false
endpoint = "unix:///var/run/docker.sock"

################################################################
# Let's encrypt
################################################################
[acme]
email = "admin@domain.tld"
storageFile = "acme.json"
onDemand = false
onHostRule = true
entryPoint = "https"

[acme.httpChallenge]
  entryPoint = "http"

[[acme.domains]]
  main = "domain.tld"
  sans = ["docker.domain.tld", "traefik.domain.tld", "phpmyadmin.domain.tld", "perso.domain.tld", "muximux.domain.tld", "wekan.domain.tld", "wiki.domain.tld", "cloud.domain.tld", "email.domain.tld"]

这是我的 docker-compose.yml(用于搬运工,这是一个可以工作的容器):

version: '2'

services:
  portainer:
    restart: always
    image: portainer/portainer:latest
    container_name: "portainer"
#Automatically choose 'Manage the Docker instance where Portainer is running' by adding <--host=unix:///var/run/docker.sock> to the command
    ports:
      - "9000:9000"
    networks:
      - traefik-network
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ../portainer:/data
    labels:
      - traefik.enable=true
      - traefik.backend=portainer
      - traefik.frontend.rule=Host:docker.domain.tld
      - traefik.docker.network=traefik-network
      - traefik.port=9000
      - traefik.default.protocol=http

networks:
  traefik-network:
    external : true

如果我访问 docker.domain.tld,它可以工作!在 https 中,使用验证让我们加密证书:)

这是我的 docker-compose.yml(对于 dokuwiki,这是一个不起作用的容器):

version: '2'

services:
  dokuwiki:
    container_name: "dokuwiki"
    image: bitnami/dokuwiki:latest
    restart: always
    volumes:
      - ../dokuwiki/data:/bitnami
    ports:
      - "8085:80"
      - "7443:443"
    networks:
      - traefik-network
    labels:
      - traefik.backend=dokuwiki
      - traefik.docker.network=traefik-network
      - traefik.frontend.rule=Host:wiki.domain.tld
      - traefik.enable=true
      - traefik.port=8085
      - traefik.default.protocol=http

networks:
  traefik-network:
    external: true

如果我访问 wiki.domain.tld,它不起作用!我在浏览器上有一个错误的网关错误。我试图将 traefik.port 更改为 7443 并将 traefik.default.protocol 更改为 https 但我有同样的错误。当然,当我尝试使用 IP 和端口(在 http / https 中)访问 wiki 时,它会起作用。仅当我键入 wiki.domain.tld 时,我的网关才错误。

所以,我不明白为什么它适用于某些容器,而不适用于具有相同声明的其他容器。

【问题讨论】:

    标签: docker traefik bad-gateway


    【解决方案1】:

    traefik 端口应该是容器的 http 端口,而不是主机上发布的端口。它通过 docker 网络进行通信,因此没有必要发布端口,这违背了仅发布单个端口并使用反向代理访问所有容器的目标。

    简而言之,你需要:

    traefik.port=80
    

    由于这个问题得到了很多关注,很多人从 traefik 看到 502 的另一个原因是将容器放在与 traefik 实例不同的 docker 网络上,或者在多个网络上拥有一个容器而不告诉 traefik 哪个网络使用。这不适用于您的情况,因为您的撰写文件中有以下几行与 traefik 服务的网络匹配:

    services:
      dokuwiki:
        networks:
          - traefik-network
        labels:
          - traefik.docker.network=traefik-network
    networks:
      traefik-network:
        external : true
    

    即使您只将服务分配给单个网络,某些操作(例如发布端口)也会导致您的服务连接到两个不同的网络(入口网络是第二个)。标签中的网络名称需要是外部名称,在您的情况下是相同的,但对于其他未将其网络指定为外部的人,它可能有一个项目或堆栈名称前缀,您可以在 @987654324 中看到@输出。

    【讨论】:

    • 哦,很棒的 BMitch,它有效!非常感谢 :) 我误解了这个变量!
    • 另一个小问题:如果我把http端口,它的作品。但是,如果我将 https 端口 (443) 放入 traefik.port 并将 https 放入 traefik.default.protocol,我会收到“内部服务器错误”。你知道为什么吗??
    • @Alextoch traefik 默认使用 http 与您的应用程序通信。它终止 tls。要重新加密请求,您需要设置 traefik.protocol=httpsdocs.traefik.io/configuration/backends/docker
    • 我已经将traefik.default.protocol=https 放入容器中。我已将其替换为 traefik.protocol=https。我有相同的结果:内部服务器错误。我查看了 traefik 网络界面,并且 URL 似乎适合后端:https://172.21.0.7:443
    • @Alextoch 您是否确认内部服务器错误来自 traefik 而不是您的应用程序?你检查了哪些日志?调试这可能需要一个不同的问题。
    【解决方案2】:

    traefik.docker.network 也必须是完全限定的网络名称。可以是外部定义的,也可以是堆栈名称前缀。

    您也可以使用docker.network=traefik-network 定义默认网络,这意味着您不必为每个容器添加标签。

    【讨论】:

      【解决方案3】:

      验证申请:

      firewall-cmd --add-masquerade --permanent
      

      发件人:https://www.reddit.com/r/linuxadmin/comments/7iom6e/what_does_firewallcmd_addmasquerade_do/

      伪装是源 NAT 的一个花哨术语。

      firewall-cmd 在这种情况下将添加一个 iptables 规则, 专门针对 nat 表中的 POSTROUTING 链。

      你可以通过运行 iptables -t nat -nvL 查看它实际上做了什么 后路由。手动创建伪装规则的典型命令 将是 iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE,其中 翻译为“对于离开接口 eth0 的数据包 路由,把它们的源地址改成eth0的接口地址”。

      这会自动添加一个连接跟踪条目,以便数据包 对于以这种方式伪装的连接有其原始 地址和端口信息在它们返回时恢复 系统。

      这些都不会让你的 Linux 系统变成路由器;那是分开的 通过执行 sysctl -w 启用的行为(对于 IPv4) net.ipv4.ip_forward=1 或 echo 1 > /proc/sys/net/ipv4/ip_forward。

      路由只是意味着系统将对其接收到的流量进行愚蠢的处理 根据该交通的目的地; iptables NAT 的东西 允许您更改在该路由之后发出的数据包 发生。

      这是一个非常简单的概述,但复杂性要高得多 以及通过以不同方式配置它可获得的可能性。

      【讨论】:

        猜你喜欢
        • 2020-06-26
        • 2018-04-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-12
        • 2019-09-05
        相关资源
        最近更新 更多