Docker:容器无法在专用网络上找到域

时间:2016-08-11 17:37:07

标签: docker docker-compose

我试图找出在不同主机上运行相同的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

我能想到的可能的差异:

  • 在OSX上有一个vm运行的docker,就像在ubuntu上一样,它本地
  • 在Ubuntu上,docker与sudo一起运行,可能会选择不同的配置设置

2 个答案:

答案 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。文档为herehere

原始答案

问题是主机正在使用dnsmasq来解析私有IP而Docker没有在主机上使用dnsmasq。

简单的解决方法是在主机上关闭dnsmasq

  1. 运行sudo vi /etc/NetworkManager/NetworkManager.conf
  2. 注释掉这一行:#dns=dnsmasq
  3. 运行sudo service network-manager restart
  4. 现在,您应该能够使用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导致冲突,所以如果你已经安装了并且可以删除它,那么先试试吧。