我知道Docker有一个嵌入式Dns解析器。
当我在自己的网桥中运行容器时:
$ docker run -it --rm --privileged --network=mybridge xxx bash
root@18243bfe6b50:/# cat /etc/resolv.conf
nameserver 127.0.0.11
options ndots:0
root@18243bfe6b50:/# netstat -anop
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name Timer
tcp 0 0 127.0.0.11:45997 0.0.0.0:* LISTEN - off (0.00/0/0)
udp 0 0 127.0.0.11:49614 0.0.0.0:*
it shows there is a dns resolver, and iptables help do a port transfer.
root@18243bfe6b50:/# iptables -nvL -t nat
.....
Chain DOCKER_OUTPUT (1 references)
pkts bytes target prot opt in out source destination
0 0 DNAT tcp -- * * 0.0.0.0/0 127.0.0.11 tcp dpt:53 to:127.0.0.11:45997
0 0 DNAT udp -- * * 0.0.0.0/0 127.0.0.11 udp dpt:53 to:127.0.0.11:49614
Chain DOCKER_POSTROUTING (1 references)
pkts bytes target prot opt in out source destination
0 0 SNAT tcp -- * * 127.0.0.11 0.0.0.0/0 tcp spt:45997 to::53
0 0 SNAT udp -- * * 127.0.0.11 0.0.0.0/0 udp spt:49614 to::53
but, which process is the dns resolver? I guess it is dockerd? but dockerd is running in host network namespace, obviously it is different with the container network namespace, also, I can not find dockerd has dns port listening in host:
root@test:~# netstat -tnop |grep dockerd
tcp 0 0 10.5.79.50:59540 10.5.79.50:2377 ESTABLISHED 3332/dockerd off (0.00/0/0)
tcp 0 0 127.0.0.1:35792 127.0.0.1:2377 ESTABLISHED 3332/dockerd off (0.00/0/0)
tcp6 0 0 10.5.79.50:2377 10.5.79.70:45934 ESTABLISHED 3332/dockerd off (0.00/0/0)
tcp6 0 0 127.0.0.1:2377 127.0.0.1:35792 ESTABLISHED 3332/dockerd off (0.00/0/0)
tcp6 0 0 10.5.79.50:2377 10.5.79.50:59540 ESTABLISHED 3332/dockerd off (0.00/0/0)
一个进程(dockerd)如何公开主机 namespace 中的某些端口和其他 namespace (容器)中的某些端口?我读了一些代码,但仍然不明白,有人可以帮助回答吗?
谢谢。
最佳答案
也许您已经发现Docker(aka Moby)内部使用libnetwork
来配置和enable the embedded DNS resolver。 Libnetwork将解析器绑定(bind)到容器的环回接口(interface),以便127.0.0.11
上的DNS查询可以(通过iptables)路由到Docker Engine中的“后端DNS解析器”。参见libnetwork type和实际的ResolveName() code。每个容器的Sandbox允许通过网络 namespace 路由DNS查询。
关于您的问题,一个进程如何可以暴露主机上和容器内的端口:在这种情况下,将处理程序线程绑定(bind)到接口(interface)将是更合适的表达。 Docker引擎创建一个容器并配置其网络 namespace ,因此它还可以通过iptables配置容器的网络接口(interface)和数据包路由。将解析程序绑定(bind)到容器的内部接口(interface)是为什么您没有在侦听端口53的主机上找到任何进程的原因。