まえがき
自社のサービスでマイクロサービスアーキテクチャを基本として設計・開発を行っています。また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が動作させている印象です。モヤッとしていた問題が解決できそうでスッキリしましたが、あまりコンテナ同士が双方向で通信しだすとコンテナ自体が密結合になってしまいそうで気をつける必要がありそうです。