当 DNS 服务器在 docker 主机中作为 docker 容器运行时,出现“来自意外来源的回复”

当 DNS 服务器在 docker 主机中作为 docker 容器运行时,出现“来自意外来源的回复”

在具有 IP 的机器上192.168.100.6,我可以运行 docker 容器并在容器内部执行 dns 而不会出现问题:

$ docker run --rm -it xenial-networking bash

root@255c2ffc38cb:/# dig registry.mynet

; <<>> DiG 9.10.3-P4-Ubuntu <<>> registry.mynet
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1540
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;registry.mynet.              IN      A

;; ANSWER SECTION:
registry.mynet.       0       IN      A       192.168.100.16

;; Query time: 0 msec
;; SERVER: 192.168.100.16#53(192.168.100.16)
;; WHEN: Thu May 17 07:54:28 UTC 2018
;; MSG SIZE  rcvd: 61

(如你所见,registry.mynet与 DNS 服务器位于同一主机中,192.168.100.16

作为参考,解析器在docker容器中的配置如下:

root@255c2ffc38cb:/# 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
nameserver 192.168.100.16
nameserver 192.168.100.4
nameserver 192.168.100.3
nameserver 192.168.100.2
search openstacklocal

(这是docker主机中解析器配置的副本),按照这些规则

在服务器实际运行的192.168.100.16机器上DNS(作为 docker 服务,请参阅下面的 Compose 配置),同样的方法不起作用:尽管解析器配置完全相同:我收到“来自意外来源的回复”,但没有名称解析:

root@e7de85671e86:/# dig registry.mynet
;; reply from unexpected source: 172.17.0.1#53, expected 192.168.100.16#53

; <<>> DiG 9.10.3-P4-Ubuntu <<>> registry.mynet
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 12820
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;registry.mynet.              IN      A

;; AUTHORITY SECTION:
.                       10800   IN      SOA     a.root-servers.net. nstld.verisign-grs.com. 2018051700 1800 900 604800 86400

;; Query time: 97 msec
;; SERVER: 192.168.100.4#53(192.168.100.4)
;; WHEN: Thu May 17 07:58:25 UTC 2018
;; MSG SIZE  rcvd: 120

此容器的解析器配置相同:

root@e7de85671e86:/# 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
nameserver 192.168.100.16
nameserver 192.168.100.4
nameserver 192.168.100.3
nameserver 192.168.100.2
search openstacklocal

回复为何来自172.17.0.1

笔记

dns服务的compose配置如下:

  dnsmasq:
    image: andyshinn/dnsmasq:2.78
    volumes:
      - ./dnsmasq/conf/dnsmasq.conf:/etc/dnsmasq.conf
      - ./dnsmasq/conf/dnsmasq.d:/etc/dnsmasq.d
      - ./dnsmasq/conf/hosts:/etc/hosts
    network_mode: "host"
    cap_add:
      - NET_ADMIN
    restart: always
    command: --log-facility=- --log-queries=extra --all-servers --conf-file=/etc/dnsmasq.conf

更新

将有问题的docker主机(机器)中的解析器更改192.168.100.16为:

$ 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
nameserver 172.17.0.1
nameserver 192.168.100.4
nameserver 192.168.100.3
nameserver 192.168.100.2
search openstacklocal

解决问题。我仍然不明白为什么192.168.100.16名称服务器在主机中运行的容器中无法正常工作192.168.100.16(在主机本身中它运行良好)

答案1

这是容器之间发夹式 NAT 的结果。请求从容器发送到主机,再发送到目标容器。响应被 NAT 回来,但您会在转换过程中看到网关的 IP。如果您需要在容器之间进行连接,您需要将两个容器放在同一个 docker 网络上,并直接连接到容器名称/端口,而不是主机和已发布的端口。

DNS 中看到的限制来自 Alpine 中的 musl。如果您在基于 Debian 的发行版中切换到 libc6,则对 DNS 响应源的要求会更加宽松,因此您不会收到错误。可以说,musl 在这里做得对,但如果您正在寻找不需要更改架构的快速修复,您可能会发现更改发出 DNS 请求的容器的基本映像更容易。

答案2

我有同样的问题。

对于面临同样问题的每个人来说:

我在 Linux(特别是 Ubuntu)上工作,我在主机上设置了 dnsmasq。同样的设置在 Mac 上有效,但在 Linux 中,即使我使用正确的 IP 地址指向我的机器(不是 localhost/127.0.0.1),里面的容器也无法解析到我的本地 dnsmasq。基本上与上面的设置相同。它不起作用。

在我专门在所有服务中使用后network: bridge,现在连接的是同一个 IP。所以,问题是,Linux 中 docker 引擎中的默认网络默认不连接到主机接口。我们必须专门为此使用桥接网络。现在,为什么它在 Mac 上可以工作?我不知道。可能是因为主机接口在 Mac 中默认是桥接的。

相关内容