/etc/nsswitch.conf and /etc/hosts woes with the Alpine (and others) Docker image and Golang

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.confor 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.

Do not forget to open 443 port while using ovftool on ESXi hosts and deploying to a vCenter

There is a pretty neat tool called ovftool that makes it easy to deploy an OVA/OVF from any source or extract the contents of an OVA. Ordinarily people would run it on their own machines but it is possible to run it on an ESXi host as well as per these articles: http://www.virtuallyghetto.com/2012/05/how-to-deploy-ovfova-in-esxi-shell.html, https://gist.github.com/ruzickap/fda71997083a41b0c6cd. However, if you tried that and tried to deploy the OVA on another vCenter from an ESXi machine you would have ran into a similar error as per this fictional example:

[root@foo:~] /vmfs/volumes/bar/OVFTool/vmware-ovftool/ovftool /vmfs/volumes/bar/qux.ova vi://foo:bar@baz.local/ 
Opening OVA source: /vmfs/volumes/ ...
The manifest validates
...
Error: Internal error: Failed to connect to server
Completed with errors

This happens because the vi:// protocol by default uses port 443 (a.k.a. HTTPS) and that is usually blocked on the ESXi side. To rectify this issue, you will have to click on your host and go here through the vSphere client:

Click on your host in vSphere, go to

Then click on

And check this box, and click ok:

Firewall properties menu

Then it should work. Try again to run the same command. Do not forget to uncheck this box when you are finished with your deployment because obviously you do not want to open ports on your precious ESXi hosts which are not used. Alternatively, you could SSH to the host and run these commands:

esxcli network firewall ruleset set --ruleset-id esxupdate --enable true

To enable port 443 which is needed for this operation. And to disable after you are done:

esxcli network firewall ruleset set --ruleset-id esxupdate --enable false

If the ruleset with name “esxupdate” does not exist then you could create your own for the 443 port and then obviously change the name “esxupdate” to your own in these examples and pictures.

EDIT: However, nowadays it might not be the best decision to run ovftool directly on ESXi hosts. Check this article out. I recommend you to move your pipe-line over to Terraform for this use-case.