net.Dial seems to ignore /etc/hosts if I don't provide GODEBUG=netdns=(c)go

2,984 views
Skip to first unread message

ondr...@gmail.com

unread,
Jan 1, 2016, 10:09:50 PM1/1/16
to golang-nuts
Hello,

I'm running 2 Docker containers linked together:

* application written in Go
* database (Postgres)

If you are not familiar with Docker, link creates entry in /etc/hosts with IP of the other container (in this case database). So after linking database container, /etc/hosts in app container looks as follows:

# cat /etc/hosts
172.17.0.32 8c70febffc58
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.31 db 23fa128ea263 vagrant_db_1

I tried to connect to database using following code (using github.com/lib/pq driver):

database, _ = sql.Open("postgres", "postgres://postgres@db:5432/test?sslmode=disable")

err = database.Ping()

if err != nil {
log.Println(err)
}

It always seemed to ignore /etc/hosts, failing with "dial tcp: lookup db on 10.0.2.3:53: server misbehaving". I expect it bypassed my hosts file and tried to resolve it via DNS. I tried to debug it using GODEBUG=netdns=... as described in https://golang.org/pkg/net/#hdr-Name_Resolution and found out that connection was successfully established when I used GODEBUG=netdns=go or GODEBUG=netdns=cgo. I find that odd since the documentation mentions that "go" is used by default, but it behaved differently when I explicitly set it.

I'm not sure if it's some problem with lib/pq, Golang or I'm misunderstading something. Any ideas what could be happening?

I'm using Go 1.5.2, running inside Alpine Linux Docker container, running inside virtual Ubuntu (Linux vagrant-ubuntu-trusty-64 3.13.0-48-generic #80-Ubuntu SMP Thu Mar 12 11:16:15 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux) on OSX El Capitan.

Dmitri Shelenin

unread,
Mar 31, 2016, 11:26:33 AM3/31/16
to golang-nuts, ondr...@gmail.com
Hey,

just hit the same thing for my service - DNS is used although the hostname is in /etc/hosts files. Thanks for the pointers to the documentation - that got me started on the research.
I checked the sources for net/conf.go for the way it is decided which  host lookup sequence to use. You're right that setting the netdns configuration option changes the lookup order - it forces it to one of the values you specify (go or cgo). I did not find any explicit mention about default behaviour being that it is forced to use the go resolver - the default actually is to use dynamic strategy.
Now, the interesting parts are in conf.hostLookupOrder (net/conf.go) which determines the lookup strategy to use. It looks at several things including /etc/nsswitch.conf (which can also define hostname resolution order).
In case there's no /etc/nsswitch.conf, it will fallback to dns+files order (note: for linux) which is probably what you're (it was the case for me!) experiencing.
So I guess the best bet is to (re-)configure the desired lookup order in /etc/nsswitch.conf

regards,
dmitri.

Peter Bourgon

unread,
Mar 31, 2016, 11:29:40 AM3/31/16
to Dmitri Shelenin, golang-nuts, ondr...@gmail.com
The problem is with Alpine, specifically musl's DNS behavior, and not
Go. See e.g. https://github.com/gliderlabs/docker-alpine/issues/8. I
believe the issue will be fixed in Alpine in the near future.
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

cpug...@gmail.com

unread,
Aug 23, 2017, 4:24:04 PM8/23/17
to golang-nuts, dee...@googlemail.com, ondr...@gmail.com
I'm not sure I agree that this is an alpine bug.
This seems to be defined here: https://golang.org/src/net/conf.go#L203


	// If /etc/nsswitch.conf doesn't exist or doesn't specify any
  	// sources for "hosts", assume Go's DNS will work fine.
  	if os.IsNotExist(nss.err) || (nss.err == nil && len(srcs) == 0) {
  		if c.goos == "solaris" {
  			// illumos defaults to "nis [NOTFOUND=return] files"
  			return fallbackOrder
  		}
  		if c.goos == "linux" {
  			// glibc says the default is "dns [!UNAVAIL=return] files"
  			// http://www.gnu.org/software/libc/manual/html_node/Notes-on-NSS-Configuration-File.html.
  			return hostLookupDNSFiles
  		}
  		return hostLookupFilesDNS
Reply all
Reply to author
Forward
0 new messages