问题描述
我安装了新的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)
怎么办?
最佳办法
当Ubuntu Docker软件包更新为使用systemd时,它放弃了对/etc/default/docker
配置文件的支持,因此初始解决方案suggested by 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设置添加到ExecStart
行:
# /etc/docker/daemon.json
{
"dns": ["10.0.0.2", "8.8.8.8"]
}
重新启动Docker守护程序:
$ sudo service docker restart
如果您需要更多详细信息,我也写了an in-depth blog post和filed a bug。
(最初,我通过打开/lib/systemd/system/docker.service并将其添加到ExecStart行中来解决该问题,但这很糟糕-我们shouldn’t edit systemd files directly。)
次佳办法
我自己不使用docker,因此通常不会在docker问题上使用butt-in,但是我只是偶然在阅读有关内容,偶然发现了一些出现在address this exact problem的docker文档。到sum-up …
该文档提出了一些解决方法。首先是通过将以下行添加到/etc/default/docker
来指定docker守护程序用于容器的DNS服务器:
docker_OPTS="--dns 8.8.8.8"
其中提供的DNS可以是本地DNS服务器,例如192.168.1.1(网关)。然后,重新启动
sudo restart docker
另一种解决方案包括通过注释掉/etc/NetworkManager/NetworkManager.conf
中的配置来禁用NetworkManager中的dnsmasq,如下所示:
#dns=dnsmasq
然后,重新启动
sudo restart network-manager
sudo restart docker
第三种办法
我在遇到这种情况时遇到了这种情况
-
在我的本地开发机器上运行Docker容器
-
哪个连接到VPN
-
我们的某些容器构建脚本执行的操作类似于从容器内VPN上的自定义存储库运行
npm install
。-
此操作通过CI管道进行,但不适用于我们的开发人员计算机,因为
npm
无法成功进行DNS查找 -
我们还遇到了容器的问题,需要进行查找才能调用外部REST API
-
Ubuntu默认情况下使用NetworkManager启动的dnsmasq
缓存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
网桥上的容器到VPNtap0
适配器上的DNS服务器之间没有路由。
-
-
抱歉,容器中的所有DNS查找均失败,因为它无法访问所提供的唯一DNS服务器
-
此外,某些网络会阻止对Google DNS服务器的请求,因为它们希望能够监听您的所有DNS查找
解决方案 :
使用NetworkManager及其设计方式的自带dnsmasq
实例似乎更为优雅。
-
告诉Docker将您的
dnsmasq
实例用于DNS-
添加或编辑文件
/etc/docker/daemon.json
以告知Docker使用docker0
网桥适配器{ "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
-
(可选)为您的域添加搜索域,以便您可以使用短名称
-
我刚刚将本地域添加到默认网络连接中的搜索列表中
-
-
-
重新启动NetworkManager和Docker
sudo service network-manager restart sudo service docker restart
此时,对于您的VPN内外域,在使用VPN时,您的Docker容器应该能够执行nslookup
,而不会出现问题。