我试图找出在不同主机上运行相同的docker容器的问题,其中一个容器可以在专用网络上找到/ ping / nslookup域,而另一个容器不能。一个主机是OSX 10.11,另一个是Ubuntu 16.04。两者都在运行docker 1.12。我使用docker-compose
来启动我的应用程序,并且我希望弄清楚发生了什么以及如何修复它,或者我可以在不诉诸硬编码域的情况下进行一些配置更改或ip地址将使容器在两台主机上的行为相同。
在我的OSX框中,我的域名自动设置了以下dns名称服务器:
osx:$ cat /etc/resolv.conf
domain redacted.lan
nameserver 172.16.20.19
nameserver 10.43.0.11
我知道大多数OSX工具都没有resolv.conf
使用,但系统偏好设置>网络显示相同的设置。
我的Ubuntu 16盒子上也有类似的设置(来自https://askubuntu.com/questions/152593/command-line-to-list-dns-servers-used-by-my-system的命令):
ubu:$ cat /etc/resolv.conf
nameserver 127.0.1.1
search redacted.lan
ubu:$ nmcli device show eno1 | grep IP4.DNS
IP4.DNS[1]: 172.16.20.19
IP4.DNS[2]: 10.43.0.11
然后,在OSX和Ubuntu上,我用这个启动我的容器:
$ docker run -it redacted_web bash
然后我运行这些命令来诊断我的问题:
$ apt-get update
$ apt-get install -y dnsutils
$ cat /etc/resolv.conf
$ nslookup redacted.lan
在OSX上,最后2个命令的输出为:
root@d19f49322fda:/app# cat /etc/resolv.conf
search local
nameserver 192.168.65.1
root@d19f49322fda:/app# nslookup redacted.lan
Server: 192.168.65.1
Address: 192.168.65.1#53
Name: redacted.lan
Address: 172.18.0.23
在Ubuntu上,输出为:
root@91e82d652e07:/app# 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
search redacted.lan
nameserver 8.8.8.8
nameserver 8.8.4.4
root@91e82d652e07:/app# nslookup redacted.lan
Server: 8.8.8.8
Address: 8.8.8.8#53
** server can't find redacted.lan: NXDOMAIN
我能想到的可能的差异:
sudo
一起运行,可能会选择不同的配置设置答案 0 :(得分:3)
更新后的答案(2017-06-20)
较新版本的Ubuntu(17.04+)不使用dnsmasq(现在使用systemd-resolved)。您将遇到与主机解析类似的问题,但此处的原始解决方案不再有效。实际上,Docker容器甚至无法与systemd-resolvd通信,因为它在容器内无法访问的位置运行自己的DNS。
对于较新版本的Ubuntu,一个很好的解决方案是将以下配置放在/etc/docker/daemon.json
中(如果该文件不存在则创建该文件):
{
"dns": ["172.16.20.19", "10.43.0.11"],
"dns-search": ["redacted.lan"]
}
这允许您配置DNS服务器和搜索域。上面的DNS IP来自原始问题,但您也可以使用自己的自定义IP。您可能希望匹配主机上的DNS配置。搜索域是可选的,您可以完全省略该行(小心您的逗号!)。同样,您可能希望匹配您的主机。
基本上,这些daemon.json选项的作用是自动将DNS配置和搜索域注入容器内的配置文件,以用于在该守护程序上启动的任何容器。这是必要的,因为由于systemd-resolved工作方式的限制,您无法使用主机中的systemd-resolved来解析容器内的DNS。文档为here和here。
原始答案
问题是主机正在使用dnsmasq来解析私有IP而Docker没有在主机上使用dnsmasq。
简单的解决方法是在主机上关闭dnsmasq 。
sudo vi /etc/NetworkManager/NetworkManager.conf
#dns=dnsmasq
sudo service network-manager restart
现在,您应该能够使用docker容器,它将正确解析您的私人DNS。
答案 1 :(得分:1)
检查docker守护程序的启动脚本,它包含以下选项以调整创建容器时使用的DNS:
$ dockerd --help
# ...
--dns=[] DNS server to use
--dns-opt=[] DNS options to use
--dns-search=[] DNS search domains to use
在Ubuntu上,我相信这些设置在/ etc / default / docker中,由/etc/init.d/docker读取。保留这些未设置值应默认为/etc/resolv.conf值。
更新:Docker's DNS networking文档有很多详细信息,可以指出正确的方向。
如果容器的/etc/resolv.conf文件中没有剩余的名称服务器条目,守护程序会将公共Google DNS名称服务器(8.8.8.8和8.8.4.4)添加到容器的DNS配置中。
看起来这可能发生在您的情况中。过滤器正在寻找本地地址,我不认为你在172.16.0.0/12私有地址的情况下会发生这种情况,但这是可能的。
您可能想知道主机的/etc/resolv.conf会发生什么 文件更改。 docker守护程序的文件更改通知程序处于活动状态 它将监视主机DNS配置的更改。
注意:文件更改通知程序依赖于Linux内核的inotify 特征。因为此功能目前与此不兼容 覆盖文件系统驱动程序,使用“覆盖”的Docker守护程序将不会 能够利用/etc/resolv.conf自动更新功能。
如果发生这种情况,那么重新启动守护程序可能会解决它并指示您希望Docker在NetworkManager之后启动。
更新#2:查看this github issue它们可能还包括172.16.0.0/12,以避免与docker的桥接网络发生冲突。如果您可以确保避免在docker中使用相同的网络,那么在/ etc / defaults / docker中传递dns服务器可能会强制执行正确的行为。在帖子的最后还提到lxc导致冲突,所以如果你已经安装了并且可以删除它,那么先试试吧。