某些容器的 Traefik > "Bad gateway"(错误 502)

Traefik > "Bad gateway" (error 502) for some containers

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

对于某些容器,它就像一个魅力,而对于其他容器,当我尝试访问这些容器时出现错误:网关错误(错误 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(对于 portainer,这是一个可以工作的容器):

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 中,使用 valide 让我们加密证书 :)

这是我的 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.

时,我的网关才会出错

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

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

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

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

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

验证应用:

firewall-cmd --add-masquerade --permanent

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

Masquerading is a fancy term for Source NAT.

firewall-cmd in this instance will be adding an iptables rule, specifically to the POSTROUTING chain in the nat table.

You can see what it has actually done by running iptables -t nat -nvL POSTROUTING. A typical command to manually create a masquerading rule would be iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE, which translates to "For packets leaving interface eth0 after they have been routed, change their source address to the interface address of eth0".

This automatically adds a connection tracking entry so that packets for connections that are masqueraded in this way have their original address and port information reinstated as they return back through the system.

None of this makes your Linux system into a router; that is separate behaviour which is enabled (for IPv4) either by doing sysctl -w net.ipv4.ip_forward=1 or echo 1 > /proc/sys/net/ipv4/ip_forward.

Routing simply means that the system will dumbly traffic it receives according to the destination of that traffic; the iptables NAT stuff allows you to alter the packets which are emitted after that routing takes place.

This is a really simple overview and there is a lot more complexity and possibilities available by configuring it in different ways.