как работает Docker Embedded DNS resolver?

Я знаю, что Docker имеет встроенный резонатор Dns.
когда я запускаю контейнер в себя мостом:

$ docker run -it --rm --privileged --network=mybridge xxx bash

[email protected]:/# cat /etc/resolv.conf  
nameserver 127.0.0.11  
options ndots:0  

[email protected]:/# 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.  

[email protected]:/# 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:  

[email protected]:~# 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) обнаруживает некоторые порты в пространстве имен хостов и некоторые порты в другом пространстве имен (контейнере)? Я прочитал какой-то код, но все равно не могу понять, может ли кто-нибудь ответить?

Благодарю.

Ответ 1

Возможно, вы уже обнаружили, что Docker (aka Moby) внутренне использует libnetwork для настройки и включения встроенного DNS-решения. Libnetwork привязывает преобразователь к интерфейсу loopback контейнера, так что запросы DNS в 127.0.0.11 могут быть маршрутизированы (через iptables) в "backend DNS resolver" в Docker Engine. См. Тип libnetwork и фактический код ResolveName(). Песочница для каждого контейнера позволяет маршрутизировать DNS-запросы через сетевые пространства имен.

Что касается вашего вопроса, как один процесс может выставлять порты на хосте и внутри контейнера: в этом случае привязка потока обработчика к интерфейсу будет более подходящим выражением. Механизм Docker создает контейнер и настраивает его пространство имен в сети, поэтому он также может настраивать сетевые интерфейсы контейнера и маршрутизацию пакетов через iptables. Привязка преобразователя к внутреннему интерфейсу контейнера является причиной того, что вы не обнаружили никакого процесса на хосте, прослушивающем порт 53.