-
Notifications
You must be signed in to change notification settings - Fork 18.7k
Description
What version of Go are you using (go version)?
$ go version go version go1.13.3 linux/amd64
Does this issue reproduce with the latest release?
Yes, it does.
What operating system and processor architecture are you using (go env)?
go env Output
$ go env GO111MODULE="" GOARCH="amd64" GOBIN="" GOCACHE="/root/.cache/go-build" GOENV="/root/.config/go/env" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="linux" GONOPROXY="" GONOSUMDB="" GOOS="linux" GOPATH="/go" GOPRIVATE="" GOPROXY="https://proxy.golang.org,direct" GOROOT="/usr/local/go" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64" GCCGO="gccgo" AR="ar" CC="gcc" CXX="g++" CGO_ENABLED="1" GOMOD="" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build004276885=/tmp/go-build -gno-record-gcc-switches"
What did you do?
- Built a go containerized Go app using best practices as documented by Docker:
- using a multi-stage build
- with
CGO_ENABLED=0 - with Alpine as the final stage for the container built
- After successful build, run the app ...
- by starting a SSH tunnel on the host system
- by starting the container with
--network=hostto let container connect to tunnel - by telling container/app to use
localhostas target to connect to:
ssh -L 59187:redis.example.com:6379 joe@bastion.example.com
docker run --net=host --rm myGoApp:latest /app/redisDoSomething -host localhost -port 59187What did you expect to see?
The Go app should consider the container's /etc/hosts file to resolve localhost to 127.0.0.1.
What did you see instead?
The Go app did not consider /etc/hosts inside the container; it queried DNS servers to resolve localhost. Actually, no /etc/hosts entry would ever be considered, all lookups are using DNS directly.
Some background / Summary
- The issue was first reported in net: Go DNS resolver does not read /etc/hosts #22846 but unfortunately closed by the reporter, as he found a work-around. Due to premature issue closure, net: Go DNS resolver does not read /etc/hosts #22846 was never really considered / commented on by Go maintainers.
- The underlying problem is that Alpine uses musl and thus has no
/etc/nsswitch.conf.
But Go, withCGO_ENABLED=0, does only consider/etc/hostsif it finds a/etc/nsswitch.conf. Alpine understandably rejects adding a/etc/nsswitch.confto work around
questionable Go behaviour (e.g. macOS also has no/etc/nsswitch.conf). - As a consequence, literally EVERYBODY introduced work-arounds due to Go's musl-antipathy
- The Alpine-based Go image
- The gitlab runner
- Hashicorp Consul
- Kubernetes
- ... and many, many others, as seen referenced in net: Go DNS resolver does not read /etc/hosts #22846
In essence, everybody following documented Docker best-practices of using multi-stage builds and disabling CGO is prone to run into this issue sooner or later. In full paranoia mode, it could even be seen as security issue, as resolving localhost via DNS could be a potential attack vector, e.g. on public hot spots?
By re-opening the issue, I'd kindly ask for review of the original issue and to reconsider whether Go's net package could be adjusted to use /etc/hosts if present, even if no /etc/nsswitch.conf is found.
The issue just consumes too much developer resources and introduces work-arounds in way too many places, IMHO. Finally, and just for laughs, we ran into this issue as some joker created a localhost entry in our LAN, pointing to his PC.