Docker:容器在专用networking上找不到域

我试图找出相同的docker集装箱在不同的主机上运行的问题,其中一个容器可以在专用networking上find/ ping / nslookup域,另一个容器不能。 一个主机是OSX 10.11,另一个是Ubuntu 16.04。 两个运行docker1.12。 我正在使用docker-compose来启动我的应用程序,并且我希望弄清楚正在发生什么事以及如何解决这个问题,或者我可以做出一些configuration更改,而不必诉诸硬编码域或IP地址,容器在两台主机上performance相同。

在我的OSX机器上,我有以下由我的域自动设置的DNS名称服务器:

 osx:$ cat /etc/resolv.conf domain redacted.lan nameserver 172.16.20.19 nameserver 10.43.0.11 

我知道,大多数OSX工具不使用resolv.conf ,但系统首选项>networking显示相同的设置。

我也有类似的设置在我的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 

我可以想到的可能的差异:

  • 在OSX上有一个虚拟机运行docker,在Ubuntu上它是本地的
  • 在Ubuntu上,docker使用sudo运行,可能会select不同的configuration设置

已更新答案(2017-06-20)

较新版本的Ubuntu(17.04+)不使用dnsmasq(它现在使用systemd-resolved)。 你会遇到与主机解决类似的问题,但原来的解决scheme在这里不再起作用。 事实上,Docker容器甚至不能与systemd-resolvd通信,因为它在一个容器内无法访问的位置运行自己的DNS。

在较新版本的Ubuntu上的一个好的解决scheme是把下面的configuration放在/etc/docker/daemon.json (如果不存在,创build这个文件):

 { "dns": ["172.16.20.19", "10.43.0.11"], "dns-search": ["redacted.lan"] } 

这使您可以configurationDNS服务器和search域。 上面的DNS IPs来自原始问题,但您也可以使用自己的自定义问题。 您可能想要匹配主机上的DNSconfiguration。 search域是可选的,你完全可以忽略该行(小心你的逗号!)。 再一次,你可能想要匹配你的主机。

本质上,这些daemon.json选项所做的是自动将DNSconfiguration和search域注入容器内的configuration文件中,以便在该守护程序上启动的任何容器。 这是必要的,因为由于systemd-resolved工作方式的限制,无法使用systemd-resolved从主机parsing容器内的DNS。 文档在这里和这里 。


原始答复

问题是主机正在使用dnsmasq来parsing私有IP,并且Docker没有在主机上使用dnsmasq。

简单的解决方法是closures主机上的dnsmasq

  1. 运行sudo vi /etc/NetworkManager/NetworkManager.conf
  2. 注释掉这一行: #dns=dnsmasq
  3. 运行sudo service network-manager restart

现在,您应该能够使用泊坞窗容器,它将正确parsing您的私人DNS。

检查docker守护进程的启动脚本,它包括以下选项来调整创build容器时使用的DNS:

 $ dockerd --help # ... --dns=[] DNS server to use --dns-opt=[] DNS options to use --dns-search=[] DNS search domains to use 

在Ubuntu上,我相信这些设置在/etc/init.d/docker中读取的/ etc / default / docker中。 保留这些未设置应该默认为/etc/resolv.conf值。


更新: Docker的DNSnetworking文档有很多细节应该指向正确的方向。

如果容器的/etc/resolv.conf文件中没有其他名称服务器条目,则守护程序会将公有Google DNS名称服务器(8.8.8.8和8.8.4.4)添加到容器的DNSconfiguration中。

这看起来可能发生在你的情况。 filter正在寻找本地地址,我不认为这是发生在你的情况与172.16.0.0/12私人地址,但它是可能的。

您可能想知道主机的/etc/resolv.conf文件发生了什么变化。 docker守护进程有一个文件更改通知程序,它将监视主机DNSconfiguration的更改。

注意:文件更改通知程序依赖于Linux内核的inotifyfunction。 由于此function当前与覆盖文件系统驱动程序不兼容,因此使用“覆盖”的Docker守护程序将无法利用/etc/resolv.conf自动更新function。

如果发生这种情况,那么重新启动守护程序可能会解决这个问题,并且会显示您希望Docker在NetworkManager之后启动。


更新#2:查看这个github问题 ,他们也可能包括172.16.0.0/12,以避免与docker的桥接networking发生冲突。 如果你可以确保避免在Docker中使用同一个networking,那么在/ etc / defaults / docker中传递dns服务器可能会强制正确的行为。 这篇文章末尾还提到lxc会引起冲突,所以如果你已经安装了并且可以删除它,那么先试一试。