If you live in a part of the world where Google is blocked (China, for example), it's likely that you suffer hostnames that don't reliably resolve inside your Docker containers. This is because Docker containers are configured by default to hit Google nameservers for hostname lookups.
We've addressed another article earlier of the year on How Docker Changed Our Workflow. Herewith a brief introduction for Docker:
What is Docker
Docker containers wrap up a piece of software in a complete filesystem that contains everything it needs to run: code, runtime, system tools, system libraries – anything you can install on a server. This guarantees that it will always run the same, regardless of the environment it is running in. What is Docker?
A "dockerized" application is a collection of pre-configured Docker containers that completely encapsulates all the servers, configuration, and code required to run an application. The containers are portable: they run exactly the same way on everyone's computer, regardless of how their computer is set up (not exactly -- more on this later).
With Docker, you can develop, deploy, test and run the application much faster, therefore shortening the time needed between writing the code and running it.
With Rich (our tech lead), we'll demonstrate this problem by spinning up an alpine container on an Ubuntu host with a fresh Docker installation. We're in China.
# docker run -ti alpine:latest sh
From inside the container, sometimes we can ping baidu.com, and other times we can't.
/ # ping baidu.com ping: bad address 'baidu.com' / # ping baidu.com PING baidu.com (22.214.171.124): 56 data bytes 64 bytes from 126.96.36.199: seq=0 ttl=53 time=41.421 ms
Let's take a look at
/etc/resolv.conf inside the container:
/ # cat /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 search lan nameserver 188.8.131.52 nameserver 184.108.40.206
Surprise, surprise: Google nameservers.
What we need to do is tell the Docker daemon to configure containers with viable DNS nameservers at container start time. Doing this is a simple matter of editing
/etc/default/docker on an Ubuntu/Debian host. The file looks something like this:
# Docker Upstart and SysVinit configuration file # # THIS FILE DOES NOT APPLY TO SYSTEMD # # Please see the documentation for "systemd drop-ins": # https://docs.docker.com/engine/articles/systemd/ # # Customize location of Docker binary (especially for development testing). #DOCKER="/usr/local/bin/docker" # Use DOCKER_OPTS to modify the daemon startup options. #DOCKER_OPTS="--dns 220.127.116.11 --dns 18.104.22.168" # If you need Docker to use an HTTP proxy, it can also be specified here. #export http_proxy="http://127.0.0.1:3128/" # This is also a handy place to tweak where Docker's temporary files go. #export TMPDIR="/mnt/bigdrive/docker-tmp"
Just uncomment the line containing
DOCKER_OPTS and supply the nameserver IPs you want your containers to hit. The following works for me in China; the first server is a public DNS server in China and the second is our LAN gateway.
Restart the Docker daemon:
# service docker restart
Now if we spin up a new container, the nameserver IPs that we added to
/etc/default/docker appear in the container's
# docker run -ti alpine:latest sh / # cat /etc/resolv.conf search lan nameserver 22.214.171.124 nameserver 192.168.10.1
In conclusion, if your access to Google nameservers is spotty, making a one-line change to the way the Docker daemon starts up will save you DNS-related headaches.