每配置容器 DNS,docker 容器应该有主机 /etc/resolv.conf 的副本并使用它。由于某种原因,我无法找出原因,这在我的计算机上不起作用。
$ cat /etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
# 127.0.0.53 is the systemd-resolved stub resolver.
# run "systemd-resolve --status" to see details about the actual nameservers.
nameserver 172.18.0.xxx
nameserver 172.18.0.yyy
nameserver 8.8.8.8
$ docker run -it --rm alpine cat /etc/resolv.conf
# This file is managed by man:systemd-resolved(8). Do not edit.
#
# This is a dynamic resolv.conf file for connecting local clients directly to
# all known uplink DNS servers. This file lists all configured search domains.
#
# Third party programs must not access this file directly, but only through the
# symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way,
# replace this symlink by a static file or a different symlink.
#
# See man:systemd-resolved.service(8) for details about the supported modes of
# operation for /etc/resolv.conf.
nameserver 8.8.8.8
nameserver 8.8.4.4
search home
我在 Ubuntu 18.04.3 LTS 上运行 Docker 版本 18.09.7,内部版本 2d0083d。
在 openvpn 对我的 /etc/resolv.conf 进行更改后,我尝试重新启动 docker 守护程序,但得到相同的结果:容器中的 resolv.conf 指向 Google DNS。
编辑:我再也无法访问出现此问题的计算机。显然,Ubuntu 18.04 应该使用 systemd-resolved,但 127.0.0.53 不在主机 /etc/resolv.conf 中。也许它被禁用了,或者 openvpn 配置错误并且无法与 systemd-resolved 正确交互。无论哪种情况,我都认为 docker 应该在启动容器时使用来自主机 /etc/resolv.conf 的名称服务器。
答案1
resolv.conf 文件似乎正在由多个守护进程、systemd 和 resolvconf 更新。您可能需要重新启动 docker 守护进程才能在最新更改后获取对 resolv.conf 文件的更改。
完成后,第二句话(和下面的段落)解释了对于拥有 127.0.0.1 名称服务器的任何人的名称服务器行之间的差异:
Docker 使每个容器的 /etc/resolv.conf 看起来像主机(docker 守护程序运行的地方)的 /etc/resolv.conf。在创建容器的 /etc/resolv.conf 时,守护程序会从主机的原始文件中过滤掉所有本地主机 IP 地址名称服务器条目。
根据您的情况,docker 引擎可能配置了不同的名称服务器。可以在多个位置注入此值。如果在 systemd 配置文件中完成,则应systemctl show docker | grep ExecStart
显示一个参数。或者可以使用 /etc/docker/daemon.json 文件进行设置。
对于遇到此问题的其他用户,docker 内部运行 DNS 服务器,该服务器将转发到用户创建的网络中的容器的服务器(localhost 除外)。因此,当您不使用默认网桥时,需要使用 127.0.0.53 的 resolv.conf 文件。这允许容器使用 DNS 相互解析。
答案2
我认为您在这里遇到的问题是 OpenVPN 的子网与 docker 内部用于容器的本地子网之间的子网冲突。如果您这样做ip addr
并查找 docker 为您的网络创建的桥接适配器,您将找到它分配给该桥的子网范围。通常它172.20.0.1/16
会与您的 OpenVPN 子网重叠。由于这会使 OpenVPN DNS IP 地址“对 docker 本地”,因此它会将它们从容器的 中删除/etc/resolv.conf
。
如果你有多个 docker 网络,但不知道应该查看哪个网桥,你可以docker network list
使用网络 ID 并在其前面加上前缀br0
。例如,ID 为 的 docker 网络28881c0a72ad
由网桥适配器 提供服务br0-28881c0a72ad
。
这个问题有几种解决方案。一种选择是更改 docker 将使用的默认地址池,方法是将其设置为daemon.json
:
vi /etc/docker/daemon.json
{
"default-address-pools" : [
{
"base" : "172.240.0.0/16",
"size" : 24
}
]
}
完成后,重新启动 docker 守护程序以重新配置默认网络。其他网络需要删除并重新创建。另一种解决方案是创建覆盖以下范围的占位网络:
docker network create --driver=bridge --subnet 172.18.0.0/24 openvpn
将来由 docker-compose 或类似工具创建的网络将不会分配给该子网。