By default, the alpine
Docker image which is mostly used for Golang programs does not contain /etc/nsswitch.conf
. Golang’s net
package used to do a sane thing when that file did not exist back in the day (before April 30, 2015) i.e. they checked the /etc/hosts
file first, and then moved on to trying to query the DNS servers.
However, it was changed later – now Go’s resolver tries to query the local machine as per the manual page of nsswitch.conf(5). You can find the commit here.
Most distributions have a file /etc/nsswitch.conf
installed by default which is set to use the files
database for name resolution first:
hosts: files dns
Thus, the easiest way to actually fix it is to mount your own local, normalnsswitch.conf
inside the Alpine container by passing this extra parameter to docker run
like so: docker run -v /etc/nsswitch.conf:/etc/nsswitch.conf
.
To further customize the name resolution, configure /etc/nsswitch.conf
as per your needs.
Even forcing Go to use the cgo
resolver wouldn’t help much in most of the cases because glibc
(the most popular libc
) follows the same exact steps in case /etc/nsswitch.conf
does not exist.
What makes it more painful is that you have to restart your Go programs after adding /etc/nsswitch.conf
or making a change in it if you use the Go’s internal resolver because it does not watch for changes and it does not automatically reload what it has in memory. I guess that Go, again, follows the principle out-lined in the aforementioned manual:
Within each process that uses nsswitch.conf, the entire file is read only once. If the file is later changed, the process will continue using the old configuration.
This affects a lot of publicly available container images that are based on Alpine. You could find a example list here.
Some of the other popular images had this issue too. For example, the Prometheus 2 months ago didn’t have that file too in their Docker image quay.io/prometheus/busybox
. This was fixed here.
So, in any way, tread the GNU/Linux container world carefully if you are developing a Go program. You might run into some confusing behavior if /etc/nsswitch.conf
does not exist. At least add a minimum one to have a proper name resolution.
Hey there.. I’m working with Docker (at home presently) and using Alpine as the bare metal host to run docker. Everything was fine until I moved my DNS into docker.. lost power and have spent the last few hours trying to understand why docker wasn’t starting up.. changing resolv.conf for bare metal alpine, seemed to fix everything.. moving it back to the local seemed to break everything starting up from scratch.. nsswitch.conf did not exist.. Alpine edge as of November 12, 2020.. after reading your post, and creating my own.. docker starts up no problem not needing recursion to resolve ‘localhost’ literally 42 dns requests (A and AAAA) looking for localhost.. – Thanks for this.