[英]Docker Swarm container cannot connect to its Docker host, connection times out
long story short: Container C on Docker Swarm host A can access Nginx ( deploy mode:global
) on Docker Swarm host B but not on Docker Swarm host A via Docker host's IP, connection timed out
.长话短说:Docker Swarm 主机 A 上的容器 C 可以访问 Nginx(
deploy mode:global
)Docker Swarm 主机 B 但不能访问 Docker Swarm 主机 A 通过 884126800538818 timed5.8 connection timed out
Long story: I have a Docker Swarm with 3 hosts.长话短说:我有一个带有 3 个主机的 Docker Swarm。 All Docker containers are running on a
scope:swarm
and driver:overlay
.network, called internal.network
.所有 Docker 容器都在
scope:swarm
和driver:overlay
.network 上运行,称为internal.network
。 On the swarm I have also 3 Nginx ( deploy mode: global
) running.在 swarm 上,我还有 3 个 Nginx(
deploy mode: global
)正在运行。 The Nginx have the default.network set to internal.network
but also ports
configuration with target:80,published:80,protocol:tcp,mode:host
(and other ports). Nginx 将 default.network 设置为
internal.network
,但ports
配置为target:80,published:80,protocol:tcp,mode:host
(和其他端口)。 The idea is that connections to the Docker swarm hosts are forwarded to the Nginx containers and then forwarded (reverse-proxied) to the Docker containers running on the swarm such as GitLab, Mattermost, and others.这个想法是将与 Docker 群主机的连接转发到 Nginx 容器,然后转发(反向代理)到运行在群上的 Docker 容器,例如 GitLab、Mattermost 等。 Moreover, the Docker swarm hosts have
keepalived
configured to share the same IP (fail over) - so no matter what Docker host this shared IP is assigned to, there is always an Nginx running to accept incoming requests.此外,Docker 群主机已将
keepalived
配置为共享相同的 IP(故障转移) - 因此无论将此共享 IP 分配给哪个 Docker 主机,始终有一个 Nginx 正在运行以接受传入请求。 I am using Oracle Linux 8 (kernel 5.4.17 el8uek) and Docker 20.10.12.我正在使用 Oracle Linux 8(内核 5.4.17 el8uek)和 Docker 20.10.12。 Docker is configured with
icc: false
and userland-proxy: false
. Docker 配置了
icc: false
和userland-proxy: false
。
In the following example addr.foo
resolves to shared ip
.在以下示例中,
addr.foo
解析为shared ip
。
What works:什么有效:
keepalived
as it occurs with the Docker hosts' IPs too.keepalived
无关,因为它也发生在 Docker 主机的 IP 上。internal.network
and Mattermost can communicate with that PostgreSQL instance on the internal.network
.internal.network
上运行,Mattermost 可以与internal.network
上的 PostgreSQL 实例通信。curl https://addr.foo
and curl https://<shared ip>
and to access Nginx and the reverse-proxied Docker containercurl https://addr.foo
和curl https://<shared ip>
并访问 Nginx 和反向代理的 8053296 容器 8053296curl https://<host ip>
and access Nginx and the reverse-proxied Docker containercurl https://<host ip>
并访问 Nginx 和反向代理的 Docker 容器curl https://addr.foo
or curl https://<shared IP>
when the shared IP is not hosted by the Docker host that is hosting the Docker container itself. curl https://addr.foo
or curl https://<shared IP>
when the shared IP is not hosted by the Docker host that is hosting Docker 容器本身。 What does not work:什么不起作用:
curl
and point to the Docker swarm host that is hosting the container.curl
并指向托管容器的 Docker 群主机。 Curl (the container, docker) resolves the IP of its own Docker swarm host (eg curl https://<Docker host name>
) which is correct but then the connection times out. curl https://<Docker host name>
),这是正确的,但随后连接超时。curl
and point to the shared IP when the shared IP is hosted by the Docker host that is running the container.curl
并指向共享 IP。 The curl
connection times out when accessing the containers Docker host.curl
连接超时。 So from inside a container it is not possible to connect to the the containers Docker host's IP but to other Docker hosts' IPs.因此,从容器内部不可能连接到容器 Docker 主机的 IP,而是连接到其他 Docker 主机的 IP。 The.network interface
ens192
on all Docker hosts is in firewall-zone public
with all necessary ports open, external access works.所有 Docker 主机上的 .network 接口
ens192
都在 firewall-zone public
中,所有必要的端口都打开,外部访问有效。
So my problem is: From within a Docker container it is not possible to establish a connection to the Docker host that is hosting the Docker container but it is possible to connect to another host.所以我的问题是:在 Docker 容器中,无法与托管 Docker 容器的 Docker 主机建立连接,但可以连接到另一台主机。
On host docker host 1 with addr.foo
resolving to docker host 2:在主机 docker 主机 1 上,
addr.foo
解析为 docker 主机 2:
docker exec -it <nginx container id> curl https://addr.foo
[...] valid response
docker exec -it <nginx container id> curl https://<docker host 2>
[...] valid response
docker exec -it <nginx container id> curl https://<docker host 1>
connection timed out
Why do I need it: Mattermost authenticates users via GitLab. Therefore, Mattermost needs to connect to GitLab. When Mattermost and GitLab are running on the same Docker swarm host, Mattermost cannot connect to GitLab.为什么需要它:Mattermost 通过 GitLab 对用户进行身份验证。因此,Mattermost 需要连接到 GitLab。当 Mattermost 和 GitLab 在同一台 Docker swarm 主机上运行时,Mattermost 无法连接到 GitLab。
What I do not want to do: Restrict GitLab and Mattermost to not run on the same swarm host.我不想做的事:限制 GitLab 和 Mattermost 不在同一群主机上运行。
I also tried to move interface docker_gwbridge
to firewall-zone trusted
which led to the problem that the Docker containers did not start up.我还尝试将接口
docker_gwbridge
移动到trusted
的防火墙区域,这导致了 Docker 容器没有启动的问题。
I hope that this is enough information to get the idea.我希望这是足够的信息来理解这个想法。
Ok, found the answer here I guess: Docker Userland Proxy .好的,我猜在这里找到了答案: Docker Userland Proxy 。
In the previous section we identified two scenarios where Docker cannot use iptables NAT rules to map a published port to a container service:
在上一节中,我们确定了两种情况,其中 Docker 无法使用 iptables NAT 规则到 map 到容器服务的已发布端口:
When a container connected to another Docker.network tries to reach the service (Docker is blocking direct communication between Docker.networks);
当连接到另一个 Docker.network 的容器尝试访问服务时(Docker 正在阻止 Docker.networks 之间的直接通信);
When a local process tries to reach the service through loopback interface.
当本地进程尝试通过环回接口访问服务时。
This is what userland-proxy
is for and setting it to true
(default) enables the desired behavior.这就是
userland-proxy
的用途,将其设置为true
(默认)可启用所需的行为。
When communicating between containers you use the service name of the docker service not the host IP.在容器之间通信时,您使用 docker 服务的服务名称,而不是主机 IP。
Try from cli of one container ping the other containers based on the service name.尝试从一个容器的 cli 根据服务名称 ping 其他容器。 If no reply then they are not on the same overlay.network.
如果没有回复,那么他们不在同一个 overlay.network 上。
Faced a similar problem.遇到了类似的问题。 In my case, nginx did not correctly determine the ip address of the container.
就我而言,nginx 没有正确确定容器的 ip 地址。 An explicit indication of the nginx's directive helped:
nginx 指令的明确指示有助于:
resolver 127.0.0.11 ipv6=off;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.