Edited at

Dockerコンテナ間で双方向通信させる

More than 3 years have passed since last update.


まえがき

自社のサービスでマイクロサービスアーキテクチャを基本として設計・開発を行っています。またDockerを用いてインフラをコード化し冪等性を担保し、どこでも同じ環境を再現でき、スケーラブルであるなど様々な恩恵を受けて、インフラもマイクロサービス特性である疎結合で高凝縮性をそのまま実現しています。

今回はちょっと困っていたコンテナ間双方向通信する方法について、解決ができたので共有しようと思いました。


これを読むとわかること ( TL;DR )


  • Dockerコンテナ間で通信する方法

  • 特にコンテナ間の双方向通信はDocker Compose version2で解決(※)


  • Docker ComposeのVersion 2 が少しわかる(チラッと)

※別の表現をするなら、docker networkを作成してdocker run時に作ったnetworkを--networkで指定すれば良いです。


解決したかったこと

マイクロサービスをベースに作成していくと、例えば、

決済サービスユーザーサービスは別のサービスとしたい場合、コンテナを別々に用意するとします。

お互いのAPIを経由して情報を取得し合いたい場合、この2つのコンテナの双方向通信ができず困ってました。


なぜ簡単ではなかったか?

(このセクション前の方法を説明しているだけなので、読み飛ばしてOKです。)

あるコンテナに別のコンテナのIPを教える場合、docker --linkが簡単です。

以下はuserコンテナからpaymentコンテナに接続する場合、名前でIPを引けるようにするdocker-compose.ymlの例です。

user:

image: nginx:1.9-alpine
ports:
- "80:80"
links:
- payment:payment
payment:
image: nginx:1.9-alpine
ports:
- "8080:80"


ping

それぞれのコンテナの中からpingを飛ばしてみます。

user => payment ( OK )

/ # ping payment

PING payment (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.095 ms

payment => user ( NG )

/ # ping user

ping: bad address 'user'

当然の動きです。userのみにpaymentが見えるように設定している為。

両方にlinkの設定を書けば良いのではないか?と

↓このようなことを試してみますと、

user:

image: nginx:1.9-alpine
ports:
- "80:80"
links:
- payment:payment
payment:
image: nginx:1.9-alpine
ports:
- "8080:80"
links:
- user:user

結果 : 怒られます

% docker-compose up -d

ERROR: Circular dependency between payment and user


解決策:Docker Compose Version2

docker-compose.ymlがこちら。

version: '2'

services:
user:
image: nginx:1.9-alpine
ports:
- "80:80"
payment:
image: nginx:1.9-alpine
ports:
- "8080:80"

linkの設定を削除し、最初の2行だけを追加しているだけです。

これで両方のコンテナから双方向に名前でIPが引けるようになります。

docker inspectでコンテナの詳細を見てみると、

(paymentのコンテナの結果の一部)

            "Networks": {

"ver2_default": {
"IPAMConfig": null,
"Links": null,
"Aliases": [
"f95e47abaaeb",
"user"
],

f95e47abaaebというコンテナのIDと、

userというサービス名がエイリアスと登録されていてこれらの影響で勝手に名前が引けるようになっているようです。

ver2_defaultというのが、docker network lsで確認できますが、docker-compose実行時に勝手にdocker network createが実行されて作成されるbridgeネットワークのようです。

% docker-compose up -d

Creating network "ver2_default" with the default driver
Recreating ver2_payment_1
Recreating ver2_user_1
% docker network ls
NETWORK ID NAME DRIVER SCOPE
f5396e5e4ee2 ver2_default bridge local

さらに興味があればdocker network inspect [NETWORK ID]を実行してみると、ネットワークに対してコンテナやそのMacAddressが登録されていることも確認できます。


まとめ

結局、Version2で記載した場合のDocker Composeの動きを書いただけの内容となってしまいましたが、Docker Engineのv1.10辺りでNetwork部分をより柔軟に進化させたものを勝手にDocker Composeが動作させている印象です。モヤッとしていた問題が解決できそうでスッキリしましたが、あまりコンテナ同士が双方向で通信しだすとコンテナ自体が密結合になってしまいそうで気をつける必要がありそうです。