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=host
to let container connect to tunnel - by telling container/app to use
localhost
as 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 59187
What 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/hosts
if it finds a/etc/nsswitch.conf
. Alpine understandably rejects adding a/etc/nsswitch.conf
to 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.