我正在开展一个项目,其中运行一个 Nginx 容器(负载均衡器),其端口 80 和 443 发布到主机,以及几个其他应用程序 Nginx 容器,其端口未发布。这三个容器都是 Docker 中自定义桥接网络的一部分,可以使用其容器名称相互通信。
我相信这是由于 Docker 的内部 DNS 在 127.0.0.11 上运行所致。然而,我注意到的一件事是,无论我将 FQDN 放入主机系统的 /etc/hosts 并将其解析为 127.0.0.1(或 127.0.1.1),它也会导致容器将此 FQDN 解析为本地 IP 地址。
这对于负载均衡器来说没问题 - 它会到达自身。对于主机系统来说也没什么问题,因为负载均衡器的端口已发布到主机系统。但它会破坏应用程序容器,因为应用程序容器正在解析自身,因此无法再通过 FQDN 到达负载均衡器。
这是我的示例 docker-compose.yaml:
version: "3.9"
services:
lb:
image: "bitnami/nginx:latest"
app1:
image: "bitnami/nginx:latest"
app2:
image: "bitnami/nginx:latest"
我的主机的 /etc/hosts:
127.0.0.1 testing.org
然后在其中一个应用程序容器内:
# cat /etc/resolv.conf
nameserver 127.0.0.11
容器 hosts 文件:
# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.23.0.2 67d3aaa71abb
决议如下:
# dig testing.org
;; ANSWER SECTION:
testing.org. 0 IN A 127.0.0.1
;; SERVER: 127.0.0.11#53(127.0.0.11)
我猜这主要是有意为之,但我找不到太多选项来控制它。
我可以删除主机 /etc/hosts 文件中的条目,在这种情况下,真正的 DNS 服务器将负责解析容器内的 FQDN,以及主机内的 FQDN。此外,我并不是第一个把它放在那里的人,我猜这是我的云提供商通过 cloud-init 做的,不确定是什么原因。
我可以为每个容器添加带有 FQDN 的显式主机条目,指向公共 IP,或者可能是负载均衡器的内部 IP,或者主机的内部 IP。这听起来像是一场维护噩梦。
我也可以不使用 Docker 的 DNS 服务,在这种情况下,我将失去在容器内部通过名称引用链接容器的能力,这是一个我不想失去的非常棒的功能。
还有其他选择吗?我遗漏了什么吗?Docker 版本 20.10.9,Compose 版本 1.29.2。Ubuntu 20.04 主机。
PS:不,testing.org 实际上并没有解析为 127.0.0.1,不过这是一次不错的尝试。
谢谢。
答案1
我在 DigitalOcean 上遇到了同样的问题,服务器名称被添加到 /etc/hosts。如果服务器名称实际上是主机名,则会发生 DNS 解析错误。就我而言,我决定通过修改服务器名称来解决问题。