某些容器的 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.
我在 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.