Docker 容器不使用主机 /etc/resolv.conf

Docker 容器不使用主机 /etc/resolv.conf

配置容器 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 或类似工具创建的网络将不会分配给该子网。

相关内容