この記事はSFC-RG Advent Calendar 2019の13日目です。
名前解決使おう!
コンテナ間通信の為だけに、コンテナのポートを外部に晒して、サーバーに対して通信していませんか?
かと言って、ランダムにIPアドレスが振られるコンテナ間の通信にIPアドレスを使うのは辛いので、Dockerが公式で用意してくれている名前解決手段を使っていこうという記事です。
Dockerネットワークのおさらい
Dockerはコンテナの通信の為に、bridge,none,hostの3種類の仮想ネットワーク装置を提供します。
overlay networkについては自分が使ったことが無い為、この記事では触れません。
このうち、主にbridgeがコンテナと外部の接続に使用され、docker runの既定の接続先として docker0 仮想ブリッジがあります。
また、docker network create
コマンドを利用することでユーザーが自由にbridgeタイプの仮想ブリッジを作成することができます。
理解が怪しいと感じたらこちらの記事がとてもわかりやすく纏めてくださっているので、おさらいしておきましょう。
Dockerにおける名前解決
Dockerではユーザーが自由に仮想ブリッジを定義できることは先ほど触れました。
このユーザー定義ブリッジには、標準のdocker0には無い機能があります。それが仮想ブリッジ毎に用意されたコンテナの名前解決機能です。
これらのユーザー定義ブリッジに接続されたコンテナは、特にオプションを付けずとも自動でコンテナ名を使った名前解決ができるようになります。またコンテナ名以外に任意の名前をつけることも可能です。
docker-composeと名前解決
docker-composeを使ったことのある人は、プロジェクト名_default でユーザー定義ブリッジが作られるのに気づいたと思われます。
docker-composeで動かしたコンテナは、指定がなければ全てこの仮想ブリッジに接続されており、この際サービス名も名前解決に使われるよう、自動で構成されます。
例えばminecraftとsqlサーバーの二つのコンテナをdocker-composeで構成した時、minecraftのコンテナからsqlサーバーをサービス名で参照できるのはこの仕組みを利用しているからです。
version: "3.7"
services:
minecraft: #このコンテナからsqlでpingを飛ばすと下のコンテナに届く
#~省略~
sql:
#~省略~
別のdocker-composeと名前解決を利用して接続するには
要は通信したいコンテナ同士を同じ仮想ブリッジに参加させてしまえば、自動で名前解決が構成されます。
注意すべき点として、docker-composeは自動構成の仮想ブリッジか既存のかはお構いなしに、サービス名での名前解決を設定します。
例えば同じネットワークに複数の同名のサービスを持ったdocker-composeを参加させると、DNSラウンドロビン状態になります。
$ nslookup nginx
nslookup: can't resolve '(null)': Name does not resolve
Name: nginx
Address 1: 192.168.160.6 webserver_.web_nw
Address 2: 192.168.160.13 mgmt-webserver_.web_nw
Address 3: 192.168.160.9 onaka-webserver_.web_nw
DNSラウンドロビンをされては困る!という場合は、docker-compose単位での一意性しか保証されないサービス名ではなく、Dockerホスト全体での一意性が保証されるコンテナ名を使うといいでしょう。
docker-composeのコンテナ名は自動生成ですが、自分はcontainer_name:を使うことでコンテナ名を固定しています。
命名規則はdocker-composeの標準に倣って、 プロジェクト名_サービス名_ にしています。
share_bridgeという名前の仮想ブリッジが存在していて、それに参加したいと仮定した場合のdocker-compose.ymlは以下のようになります。
version: "3.7"
services:
nginx:
image: nginx:latest
container_name: qiita_nginx_
networks:
- share
- default #自動作成の仮想ブリッジにも参加できる。
#~省略~
networks:
share: #docker-compose.yml内でだけの仮想ブリッジ名
external: true #既存の仮想ブリッジを使う
name: share_bridge #ホストでの仮想ブリッジ名
これを実行すると、qiita_nginx_という名前のコンテナが、share_bridgeに参加している他のコンテナからコンテナ名で接続できるようになります。
参考文献
Docker container networking
Docker network 概論
Networking in Compose