Help us understand the problem. What is going on with this article?

docker-composeを跨いだコンテナ間の名前解決について

この記事は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サーバーをサービス名で参照できるのはこの仕組みを利用しているからです。

docker-compose.yml
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は以下のようになります。

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

negineri
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした