You might not realize it but Docker, by default, provides your containers a means to do basic name resolution. Docker passes name resolution from the Docker host, directly into the container. The result is that a spawned container can natively resolve anything that the Docker host itself can. The mechanics used by Docker to achieve name resolution in a container are elegantly simple. In this recipe, we'll walk through how this is done and how you can verify that it's working as expected.
In this recipe, I’ll be demonstrating the configuration on a single Docker host. It’s assumed that this host has Docker installed and that Docker is in its default configuration. We'll be altering name resolution settings on the host so you'll need root-level access.
How to do it…
To start with, let's start a new container on our host docker1 and examine how the container handles name resolution:
user@docker1:~$ docker run -d -P --name=web8 \
user@docker1:~$ docker exec web8 host www.google.com
www.google.com has address 18.104.22.168
www.google.com has IPv6 address 2607:f8b0:4009:80e::2004 user@docker1:~ $
It would appear that the container has the ability to resolve DNS names. If we look at our local Docker host and run the same test, we should get similar results:
user@docker1:~$ host www.google.com
www.google.com has address 22.214.171.124
www.google.com has IPv6 address 2607:f8b0:4009:80e::2004
In addition, just like our Docker host, the container can also resolve local DNS records associated with the local domain lab.lab:
user@docker1:~$ docker exec web8 host docker4
docker4.lab.lab has address 192.168.50.102
You'll notice that we didn't need to specify a fully qualified domain name in order to resolve the host name docker4 in the domain lab.lab. At this point it's safe to assume that the container is receiving some sort of intelligent update from the Docker host which provides it relevant information about the local DNS configuration.
In case you don't know, the resolv.conf file is generally where you define a Linux system's name resolution parameters. In many cases it is altered automatically by configuration information in other places. However, regardless of how it's altered, it should always be the source of truth for how the system handles name resolution.
To see what the container is receiving, let's examine the containers resolv.conf file:
user@docker1:~$ docker exec -t web8 more /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
As you can see, the container has learned that the local DNS server is 10.20.30.13 and that the local DNS search domain is lab.lab. Where did it get this information? The solution is rather simple. When a container starts, Docker generates instances of the following three files for each container spawned and saves it with the container configuration:
These files are stored as part of the container configuration and then mounted into the container. We can use findmnt tool from within the container to examine the source of the mounts:
root@docker1:~# docker exec web8 findmnt -o SOURCE
…<Additional output removed for brevity>…
So while the container thinks it has local copies of the hostname, hosts, and resolv.conf, file in its /etc/ directory, the real files are actually located in the containers configuration directory (/var/lib/docker/containers/) on the Docker host.
When you tell Docker to run a container, it does three things:
- It examines the Docker hosts /etc/resolv.conf file and places a copy of it in the containers directory.
- It creates a hostname file in the containers directory and assigns the container a unique hostname.
- It creates a hosts file in the containers directory and adds relevant records including localhost and a record referencing the host itself.
Each time the container is restarted, the container's resolv.conf file is updated based on the values found in the Docker hosts resolv.conf file. This means that any changes made to the resolv.conf file are lost each time the container is restarted. The hostname and hosts configuration files are also rewritten each time the container is restarted losing any changes made during the previous run.
To validate the configuration files a given container is using we can inspect the containers configuration for these variables:
user@docker1:~$ docker inspect web8 | grep HostsPath
user@docker1:~$ docker inspect web8 | grep HostnamePath
user@docker1:~$ docker inspect web8 | grep ResolvConfPath
As expected, these are the same mount paths we saw when we ran the findmnt command from within the container itself. These represent the exact mount path for each file into the containers /etc/ directory for each respective file.
This is a chapter excerpt from "Docker Networking," written by Jon Langemak and published by Packt. Through Jan. 9, 2017, Packt is offering every ebook on its website for just $5.