2020 年编辑:这是一个六年前的问题。我当时从未弄清楚如何解决这个特定问题,但 Docker 和其他相关内容都在继续发展。SE 不允许我删除我的问题,但它不再相关。
我安装了新的 Ubuntu 14.04,想使用 Docker 来运行需要 12.04 的旧东西。Docker 中的 DNS 不起作用。
我的笔记本电脑的 resolv.conf 如下所示:
nameserver 127.0.0.1
显然,这不适用于 Docker。因此,它会尝试将名称服务器设置为 8.8.8.8 和 8.8.4.4;当我这样做时
$ sudo docker run -i -t ubuntu /bin/bash
它说:
WARNING: Local (127.0.0.1) DNS resolver found in resolv.conf and containers can't use it. Using default external servers : [8.8.8.8 8.8.4.4]
果然,在 Docker 实例内部,resolv.conf 如下所示:
nameserver 8.8.8.8
nameserver 8.8.4.4
我可以从 Docker 实例中成功 ping 这两个。但是,没有 DNS(例如,ping google.com
失败)。
Docker 内部的 ifconfig 输出:
eth0 Link encap:Ethernet HWaddr aa:e9:9f:83:9d:92
inet addr:172.17.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::a8e9:9fff:fe83:9d92/64 Scope:Link
UP BROADCAST RUNNING MTU:1500 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:9 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:648 (648.0 B) TX bytes:738 (738.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
怎么办?
答案1
当 Ubuntu Docker 软件包更新为使用 systemd 时,它不再支持/etc/default/docker
配置文件,因此最初的解决方案rocketman10404 建议将不再起作用(禁用dnsmasq
仍然有效,但其缺点是阻止 Ubuntu 自动更新 DNS 服务器)。
在新daemon.json
配置文件中修复
查找您的网络的 DNS 服务器:
$ nmcli dev show | grep 'IP4.DNS'
IP4.DNS[1]: 10.0.0.2
打开或创建(如果不存在)/etc/docker/daemon.json
并添加要使用的 DNS 服务器:
# /etc/docker/daemon.json
{
"dns": ["10.0.0.2", "8.8.8.8"]
}
重新启动docker守护进程:
$ sudo service docker restart
我写一篇深入的博客文章并且提交了错误如果您想了解更多详细信息,请参阅有关此问题的说明。
(最初我通过打开 /lib/systemd/system/docker.service 并将 DNS 设置添加到 ExecStart 行来解决这个问题,但这很糟糕 - 我们不应直接编辑 systemd 文件。
答案2
我自己不使用docker,所以我通常不会在这里插话讨论docker的问题,但我碰巧读到了关于docker的文章,并偶然发现了一些docker文档,这些文档似乎解决这个确切的问题。 总结...
文档提出了一些解决方法。首先是通过添加以下行来指定 docker 守护程序要为容器使用的 DNS 服务器/etc/default/docker
:
docker_OPTS="--dns 8.8.8.8"
其中提供的 DNS 可以是本地 DNS 服务器,例如 192.168.1.1(网关)。然后,使用以下命令重新启动
sudo restart docker
另一种解决方案是通过注释掉 NetworkManager 中的配置来禁用 dnsmasq,/etc/NetworkManager/NetworkManager.conf
如下所示:
#dns=dnsmasq
然后重新启动
sudo restart network-manager
sudo restart docker
答案3
我在我的处境中遇到了这个问题,具体来说
- 在我的本地开发机器上运行 Docker 容器
- 已连接到 VPN
- 我们的一些容器构建脚本会执行
npm install
从自定义存储库运行等操作在 VPN 上,在容器内。- 这在 CI 管道中是可行的,但在开发人员的机器上却行不通,因为
npm
无法成功进行 DNS 查找 - 我们还遇到了需要查找以调用外部 REST API 的容器问题
- 这在 CI 管道中是可行的,但在开发人员的机器上却行不通,因为
Ubuntu 默认使用dnsmasq
NetworkManager 启动的缓存 DNS 请求,并配置/etc/resolv.conf
为指向此实例127.0.1.1
- 我们使用的 VPN 客户端与 NetworkManager 不兼容,并强制使用自己的客户端
/etc/resolv.conf
,从而覆盖 NetworkManager 配置 - 这将配置 VPN 的 DNS 服务器
- Docker
/etc/resolv.conf
默认将你的镜像保存到容器中- 通常在 Ubuntu 上,它会将 Google DNS 服务器传递给容器(因为它知道情况
dnsmasq
。 - 但它很乐意将 VPN DNS 服务器配置传递给容器
- 没有从
docker0
网桥上的容器到 VPN 适配器上的 DNS 服务器的路由tap0
。
- 通常在 Ubuntu 上,它会将 Google DNS 服务器传递给容器(因为它知道情况
- 因此,容器中的所有 DNS 查找都会失败,因为它无法访问其唯一提供的 DNS 服务器
- 此外,一些网络会阻止对 Google DNS 服务器的请求,因为他们希望能够窥探您的所有 DNS 查找
解决方案 :
dnsmasq
按照设计的方式使用 NetworkManager 和它的绑定实例似乎更加优雅。
告诉 Docker 使用你的
dnsmasq
实例进行 DNS添加或编辑文件
/etc/docker/daemon.json
以告诉 Docker 使用docker0
桥接适配器进行 DNS{ "dns": ["172.17.0.1"] }
配置 NM
dnsmasq
实例以监听 Docker 网桥,因为默认情况下它只监听 127.0.1.1 - 创建文件/etc/NetworkManager/dnsmasq.d/docker-bridge.conf
# Default Docker bridge interface=docker0 # Other Docker bridges interface=br-*
我不喜欢该 VPN 客户端的粗鲁行为,我宁愿只使用 VPN 端的 DNS 进行 VPN 查找(如果您有一个使用 NetworkManager 正确配置的礼貌 VPN 客户端,则您不必这样做)
- 关闭 VPN 客户端中的 DNS 功能(它会停止
resolv.conf
连接时的覆盖,现在所有 DNS 都会再次通过dnsmasq
) 添加一个配置文件来告诉
dnsmasq
您如何正确地引导您域的 DNS 请求 - 添加文件 `/etc/NetworkManager/dnsmasq.d/vpn-dns.confserver=/myprivatedomain.net/10.0.0.1 # or whatever your private DNS server is
(可选)为您的域添加搜索域,以便您可以使用短名称
- 我刚刚将我们的本地域添加到我的默认网络连接的搜索列表中
- 关闭 VPN 客户端中的 DNS 功能(它会停止
重新启动 NetworkManager 和 Docker
sudo service network-manager restart sudo service docker restart
此时,当您使用 VPN 时,您的 Docker 容器应该能够nslookup
毫无问题地运行,无论是 VPN 内部还是外部的域。
答案4
我遇到了类似的问题,将其报告给 StackOverflow。我似乎无法查询8.8.8.8
Docker 默认 Ubuntu 安装中指定的名称服务器;但是,我可以 ping 它。在这种情况下,请使用您实际可以查询的 DNS 服务器。使用以下方法测试
nslookup - dns.server.name
并通过启动容器
docker run --dns=ip.addr.of.dns
我还没有找到办法https://askubuntu.com/q/607172/30266得出一个自动化的解决方案。