Dockerコンテナ間の通信で、pingは成功するがnslookupに失敗する

Dockerコンテナ間の通信で、pingは成功するがnslookupに失敗する

Docker間(正確にはdocker-composeのserviceコンテナ間)の通信ができなくて1日つぶしました。docker-composeを使ったことはあるので、ユーザ定義の同一ネットワークにコンテナをぶら下げればよいとおもっていたのですが、なかなかつながらず。特に悩んだのはpingは成功するのですが、nslookupで名前解決できないという状況でした。

状況

docker-composeをつかっています。事前にnetworkをtest-nwという名前で生成して、externalネットワークとしてcomposeファイルに指定しました。servicesとして、複数のコンテナを登録します。
container_nameにtest_container_aとtest_container_bという名前を設定してました。

片方のコンテナ内からping/nslookupをもう片方へしたのですが、pingは成功して、nslookはNXDOMAINエラーが表示されます。

調べたこと

pingもnslookupも同じだろうと思っていて、なぜ結果が違うのかわからなかったのですが、どうやらpingとnslookupは名前解決のプロセスが違うらしく、同じ正引きをしても、結果が変わることがあるようです。ただし見つかる情報はキャッシュが残っているとかの一時的なもののしか見つかりませんでした。OS再起動してもどうしてもnslookupは一切つながりません。

原因と暫定対処①

試行錯誤の末に、コンテナ名.ネットワーク名(つまり、test_container_a.test-nw)でnslookupが成功するようになりました。厳密な理由がわかってませんがネットワークを指定しないとコンテナ名をうまく引けません。他に原因がある気がしますが、一歩前進。

問題②

やっとnslookupは成功したのですが、wgetを試してみたところ、なぜか400が返ってきました。Bad Request。そして接続先のサーバのログを見ていると、そこにさらなる原因が書かれてました。

java.lang.IllegalArgumentException: The character [_] is never valid in a domain name.

「ドメイン名にアンダースコア(_)は有効ではない」

あまり意識したことはありませんでしたが、container_nameにtest_container_aと、アンダースコアを使用していたことが問題でした。おそらくpingの過程では問題扱いされてないと思われますが、nslookupなどTCPプロトコルでは問題になるのだと思います。名称の設定箇所がcontainer_nameのため、そのままアンダースコアを使用していましたが、それはルール違反です。

暫定の解決方法②

container_nameからアンダースコアを削除して、test-container-aとしました。接続する際には、test-container-name.test-nwとして接続できました。