Learn about Docker DNS. How docker container DNS works? How to change nameserver in Docker container to use external DNS?
Docker container has inbuilt DNS which automatically resolves IP to container names in user-defined networks. But what if you want to use external DNS into the container for some project need. Or how to use external DNS in all the containers run on my host? In this article, we will walk you through the below points :
- Docker native DNS
- Nameservers in Docker
- How to use external DNS in the container while starting it
- How to use external DNS in all the containers on a docker host
Docker native DNS
In a user-defined docker network, DNS resolution to container names happens automatically. You don’t have to do anything if your containers are using your defined docker network they can find each other with hostname automatically.
We have 2 Nginx containers running using my newly created docker network named kerneltalks. Both Nginx containers are installed with ping utility.
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1b1bb99559ac nginx "nginx -g 'daemon of…" 27 minutes ago Up 27 minutes 80/tcp nginx2
239c662d3945 nginx "nginx -g 'daemon of…" 27 minutes ago Up 27 minutes 80/tcp nginx1
$ docker network inspect kerneltalks
"Containers": {
"1b1bb99559ac21e29ae671c23d46f2338336203c96874ac592431f60a2e6a5de": {
"Name": "nginx2",
"EndpointID": "4141f56fe878275e322b9283476508d1135e813d12ea2b7d87a5c3d0db527f79",
"MacAddress": "02:42:ac:13:00:05",
"IPv4Address": "172.19.0.5/16",
"IPv6Address": ""
},
"239c662d3945031413e4c69b99e3ddde57832004bd6193bdbc30bd5e6ca6f4e2": {
"Name": "nginx1",
"EndpointID": "376da79e6746cc80d178f4363085e521a9d45c65df08248b77c1bc744b495ae4",
"MacAddress": "02:42:ac:13:00:04",
"IPv4Address": "172.19.0.4/16",
"IPv6Address": ""
},
And they can ping each other without any extra DNS efforts. Since user-defined networks have inbuilt DNS which resolves IP addresses from container names.
$ docker exec -it nginx1 ping nginx2
PING nginx2 (172.19.0.5) 56(84) bytes of data.
64 bytes from nginx2.kerneltalks (172.19.0.5): icmp_seq=1 ttl=64 time=0.151 ms
64 bytes from nginx2.kerneltalks (172.19.0.5): icmp_seq=2 ttl=64 time=0.053 ms
$ docker exec -it nginx2 ping nginx1
PING nginx1 (172.19.0.4) 56(84) bytes of data.
64 bytes from nginx1.kerneltalks (172.19.0.4): icmp_seq=1 ttl=64 time=0.088 ms
64 bytes from nginx1.kerneltalks (172.19.0.4): icmp_seq=2 ttl=64 time=0.054 ms
But in default docker bridge network (which installs with docker daemon) automatic DNS resolution is disabled to maintain container isolation. You can add container inter-comm just by using --link
option while running container (when on default bridge network)
--link
is a legacy feature and may be removed in upcoming features. So it is always advisable to use user-customized networks rather than using default docker networks.
DNS nameservers in Docker
Docker is coded in a smart way. When you run a new container on the docker host without any DNS related option in command, it simply copies host’s /etc/resolv.conf
into container. While copying it filter’s out all localhost IP addresses from the file. That’s pretty obvious since that won’t be reachable from container network so no point in keeping them. During this filtering, if no nameserver left to add in container’s /etc/resolv.conf
the file then Docker daemon smartly adds Google’s public nameservers 8.8.8.8
and 8.8.4.4
in to file and use it within the container.
Also, host and container /etc/resolv.conf
always be in sync. Docker daemon takes help from the file change notifier and makes necessary changes in the container’s resolve file when there are changes made in the host’s file! The only catch is these changes will be done only if the container is not running. So to pick up changes you need to stop and start the container again. All stopped containers will be updated immediately after the host’s file changes.
How to use external DNS in container while starting it
If you want to use external DNS in the container other than docker native or other than what’s in host’s resolv.conf
file, then you need to use --dns
switch in docker container run
command.
$ docker container run -d --dns 10.2.12.2 --name nginx5 nginx
fbe29f22bd5f78213163532f2529c5cd98bc04573a626d0e864e670f96c5dc7a
$ docker exec -it nginx5 cat /etc/resolv.conf
search 51ur3jppi0eupdptvsj42kdvgc.bx.internal.cloudapp.net
nameserver 10.2.12.2
options ndots:0
In the above example, we chose to have nameserver 10.2.12.2 in the container we run. And you can see /etc/resolv.conf
inside the container saves this new nameserver in it. Make a note that whenever you are using --dns
switch it will wipe out all existing nameserver entries within the container and keeps only the one you supply.
This is a way if you want to use custom DNS in a single container. But what if you want to use this custom DNS to all containers which will run on your docker host then you need to define it in the config file. We are going to see this in the next point.
How to use external DNS in all the containers on docker host
You need to define the external DNS IP in docker daemon configuration file /etc/docker/daemon.json
as below –
{
"dns": ["10.2.12.2", "3.4.5.6"]
}
Once changes saved in the file you need to restart docker daemon to pick up these new changes.
root@kerneltalks # systemctl docker restart
and it’s done! Now any container you run fresh on your docker host will have these two DNS nameservers by default in it.
$ docker container run -d --name nginx7 nginx
200d024ac8930c5bfe59fdbc90a1d4d0e8cd6d865f82096c985e23f1e022d548
$ docker exec -it nginx7 cat /etc/resolv.conf
search 51ur3jppi0eupdptvsj42kdvgc.bx.internal.cloudapp.net
options ndots:0
nameserver 10.2.12.2
nameserver 3.4.5.6
If you have any queries/feedback/corrections, let us know in the comment box below.
Correct command is “systemctl restart docker”