Go 1.7の名前解決の仕様変更とDockerのscratchイメージの組み合わせで少しハマったのでそのメモです。
Go 1.7の名前解決の仕様
Go 1.6までpure Goの名前解決の実装は/etc/hosts
を先に読み、なければDNSを引くという順序で固定でした。参考: Go 1.6のnet/conf.go
Go 1.7からはpure Goの実装でも/etc/nsswitch.conf
の設定に基づいた順番で名前解決を行うようになりました。 参考: net: allow netgo to use lookup from nsswitch.conf
The pure Go name resolution implementation now respects nsswitch.conf's stated preference for the priority of DNS lookups compared to local file (that is, /etc/hosts) lookups.
Go 1.7 Release Notes
nsswitch.conf
が存在しない場合は、Go 1.6までと違ってDNSルックアップが優先で、引けなければ/etc/hosts
を見るという順番がデフォルトになり挙動が変わります。なおこの挙動はglibcのデフォルト(dns [!UNAVAIL=return] files
)と同じにしているようです。 参考: net/conf.go#L200-L211
nsswitch.confが存在しないとき
GoでビルドしたバイナリをDockerイメージで動かすとき、ベースイメージにscratchやAlpine Linuxなどを選択することがあると思います。scratchやAlpine Linuxにはglibcが入っていないのでnsswitch.conf
が存在しません。そのため1. 7でビルドしたタイミングからDNSルックアップが優先されるようになるので注意が必要です。
自分はdocker-composeのlink機能で/etc/hosts
に設定されるホスト名を使っていて、さらに運悪くDNSで引けるホスト名だったので1.7でビルドしてからリンクしたコンテナに繋げなくなりハマりました。Dockerのホスト側の/etc/hosts
に同じホスト名の設定が入っている場合もコンテナ側からDNSで引けてしまうので注意が必要です。
ひとまずDockerイメージに/etc/nsswitch.conf
を含めることで解決しました。