Skip to content

Conversation

@dkelleher
Copy link

The default behavior of the golang net package is to use the pure go
implementation which sends DNS requests directly to the servers listed
in resolv.conf. This breaks when running the docker client inside a
docker container that's 'linked' with other containers given that those
links utilize teh /etc/hosts to function. This change forces golang's
netdns to use cgo which uses the system c libraries and respects
nsswitch.

Before this change any short name conflict will result in the DNS query
resolving to a remote host instead of the linked container. For
example, docker will resolve to docker.rc.fas.harvard.edu instead of
the linked container due to the search domain in /etc/resolv.conf.

The default behavior of the golang net package is to use the pure go
implementation which sends DNS requests directly to the servers listed
in resolv.conf.  This breaks when running the docker client inside a
docker container that's 'linked' with other containers given that those
links utilize teh /etc/hosts to function.  This change forces golang's
netdns to use cgo which uses the system c libraries and respects
nsswitch.

Before this change any short name conflict will result in the DNS query
resolving to a remote host instead of the linked container.  For
example, docker will resolve to docker.rc.fas.harvard.edu instead of
the linked container due to the search domain in /etc/resolv.conf.
@dkelleher
Copy link
Author

I should also note this is documented at golang.org

@tianon
Copy link
Member

tianon commented Feb 6, 2017

Aren't Docker's official release binaries explicitly compiled with -tags netgo, and thus overriding this choice directly at compilation time?

IMO it might be better to instead document adding -e GODEBUG=netdns=cgo and what the difference is (if we can find a simple way to verify the behavior), or add ENV GODEBUG="netdns=cgo" to the Dockerfile if it's determined that using this behavior by default does make sense (in which case, shouldn't upstream consider adding code to handle this automatically?)

@dkelleher
Copy link
Author

dkelleher commented Feb 8, 2017

I didn't see where the Docker official release binaries are compiled with -tags netgo but I must have missed it. The way I read the documentation this choice can always be made to runtime using the GODEBUG=netdns=cgo and if it is explicitly compiled that way our tests show that the GODEBUG variable does override this.

My argument against documentation is, using netgo with a search domain can breaks the container linking which is critical to the functionality of the Docker in Docker setup. Additionally it breaks it in a very subtle way in order to save one system thread.

I also wrestled with sending this upstream but found some arguments about similar go applications which asserted that this was a problem with the application or language and could be solved other ways. I settle on putting it here because it minimized the impact of the change but I'm totally open to sending this upstream.

@jtriley
Copy link

jtriley commented Feb 13, 2017

IMHO golang should provide cgo as the default netdns implementation and provide a mechanism (e.g. env variable) for choosing the pure GO resolver as an optimization which it clearly is:

By default the pure Go resolver is used, because a blocked DNS request 
consumes only a goroutine, while a blocked C call consumes an operating 
system thread.

from: https://golang.org/src/net/net.go

Also the docs claim it will switch to cgo under a variety of circumstances including if nsswitch.conf declares something it doesn't support but this clearly has issues:

golang/go#11450

I think this is a worthwhile change unless there's a really compelling reason not to rely on the system C libraries for dns lookups.

It's a good question whether docker upstream should also force cgo...

@yosifkit
Copy link
Member

yosifkit commented Jun 1, 2017

It looks like -tags netgo was officially added in moby/moby#2162 and fixed for newer go versions in moby/moby#10087. I am doubting they would change it since they use it to be able to create a fully static binary and we try to keep as close to upstream releases as possible. I would suggest just using -e GODEBUG=netdns=cgo when using a search domain.

@tianon
Copy link
Member

tianon commented Oct 11, 2017

See #84, which adds an appropriate /etc/nsswitch.conf telling Go's netgo resolver to check /etc/hosts before doing a DNS lookup, matching Debian's default configuration. 👍

@dkelleher
Copy link
Author

Awesome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants