I know Docker has a embedded Dns resolver.
when I run a container in myself bridge:
$ 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)
how does one process(dockerd) expose some ports in host namespace and some ports in other namespace(container)? I read some code, but still can not figure out, could anyone help answer?
thanks.
Docker containers take DNS IPs from the host machine, which is managed by systemd-resolve . Those IPs themselves are the cloud provider's DNS.
DNS services conf configuration file. Containers that use the default bridge network get a copy of this file, whereas containers that use a custom network use Docker's embedded DNS server, which forwards external DNS lookups to the DNS servers configured on the host.
Here's the gist: For containers to communicate with other, they need to be part of the same “network”. Docker creates a virtual network called bridge by default, and connects your containers to it. In the network, containers are assigned an IP address, which they can use to address each other.
Run docker network ls to get the running networks names, and then docker network inspect NETWORK_NAME to see the containers in it. Look for the "Containers" keyword in the JSON, it is a list of connected devices. Look for the instance with the "IPv4Address": "127.0. 0.11/24" entry, the "Name" key is the DNS name.
Maybe you have already found that Docker (aka Moby) internally uses libnetwork
to configure and enable the embedded DNS resolver. Libnetwork binds the resolver to the container's loopback interface, so that DNS queries at 127.0.0.11
can be routed (via iptables) to the "backend DNS resolver" in the Docker Engine. See the libnetwork type and the actual ResolveName() code. The Sandbox for each container allows to route DNS queries through the network namespaces.
Regarding your question how one process can expose ports on the host and inside a container: in this case binding a handler thread to an interface would be a more appropriate expression. The Docker engine creates a container and configures its network namespace, so it can also configure the container's network interfaces and packet routing via iptables. Binding the resolver to the container's internal interface is the reason why you haven't found any process on the host listening on port 53.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With