【 docker ... create ... コマンド無し 】docker-compose.yml だけで複数の docker-compose 間の volume、network を共有する知見まとめ

# 本記事の流れ

- はじめに
- 読者の想定
- この記事に書いてあること
- 共有の手順と動作確認
  - volume 共有設定と動作確認
  - network 共有設定と動作確認
- さいごに

# はじめに

こんにちは、[Anyflow 株式会社](https://anyflow.co.jp/) ( 株式会社ピケから社名を変更 ) の古内と申します。
以前、Django, DRF の記事を書きました。( [Django REST Framework で API サーバーを実装して得た知見まとめ(OAuthもあるよ）](https://qiita.com/furuuchin/items/c6d6230aa327ad7b337a) )

今回は docker-compose についての知見を共有しようと思います。
知見を共有しようと思った経緯は以下のような感じです。

1. サーバサイドの docker-compose が複数になってしまった
2. 1 つの docker-compose にはしたくない
3. `docker network create ...` 的な事前に専用のコマンド叩きたくない
4. `docker-compose up` コマンドだけで環境を作れるようにしよう！

です。

イメージ的には

![DockerCompose.png](https://qiita-image-store.s3.amazonaws.com/0/193294/8e8774a8-b13b-bf34-c013-1a72e1a8c550.png)

がゴールです。

こちらのサンプルコードを例に解説していきます。
https://github.com/furuuchitakahiro/shared-docker-compose-example

今回の知見が何かの助けになれば幸いです。

# 読者の想定

- docker の使用経験がある
- docker-compose の使用経験がある

# この記事に書いてあること

今回の記事はでは**開発環境を docker-compose で運用している人を想定**しています。
理由は、弊社では開発環境を docker-compose、本番環境を GCP の GAE などのマネージドの環境で運用しているため、開発環境の docker-compose をセキュアでスケールする必要がないためです。 ( そもそも本番に docker-compose ってあんまりないとは思いますが )
また、今回の記事では特に Django などのフレームワークや MySQL などのデータベース等の実装のことも書いていません。
基本的にコンテナの管理 ( docker-compose ) のみに焦点を当てています。

# 共有の手順と確認

それでは先程も載せましたがこちらのソースコードで軽い説明をしていきます。
https://github.com/furuuchitakahiro/shared-docker-compose-example

実際に動かしてやりたい方のコマンドは以下になります。( 2. と 3. の順番は大切です )

1. `git clone https://github.com/furuuchitakahiro/shared-docker-compose-example.git`
2. `cd shared-docker-compose-example/master_docker-compose && docker-compose up`
3. 別のターミナルを開いて `cd shared-docker-compose-example/slave_docker-compose && docker-compose up`

このリポジトリのコンセプトとしては master_docker-compose が親になり、そこに紐づく子として slave_docker-compose の関係になります。
そのため最初に親の docker-compose を立ち上げなければ volume と network が Docker 上に生成されないので slave_docker-compose の初期化ができません。
一度親の docker-compose を立ち上げさえすれば大丈夫です。
**重要なことは `docker-compose up` コマンドの順番だけです。**

## volume 共有設定と動作確認

それではまず、 volume を見てみます。
2 つの docker-compose は動かしている前提です。

まずは設定です.

[shared-docker-compose-example/master_docker-compose/docker-compose.yml](https://github.com/furuuchitakahiro/shared-docker-compose-example/blob/master/master_docker-compose/docker-compose.yml#L12-L18) ( 親の docker-compose.yml )
12 ~ 18 行目

```yml
volumes:
  master_volume:
    driver: local
    driver_opts:
      device: ${PWD}/master_service/src
      type: volume
      o: bind
```

この設定で `docker-compose up` を実行すると volume が生成されます。
```${PWD}``` の設定部分がミソです。これでカレントディレクトリ ( docker-compose.yml のあるディレクトリ ) を指定できます。
次に、子の docker-compose を立ち上げて親の volume をマウントします。

[shared-docker-compose-example/slave_docker-compose/docker-compose.yml](https://github.com/furuuchitakahiro/shared-docker-compose-example/blob/master/slave_docker-compose/docker-compose.yml#L13-L16) ( 子の docker-compose.yml )
13 ~ 16 行目

```yml
volumes:
  master_volume:
    external:
      name: master_docker-compose_master_volume
```

この設定で親の volume をマウントできます。
試しに、slave_service コンテナを操作して確認してみましょう。

1. `cd shared-docker-compose-example/slave_docker-compose`
2. `docker-compose exec slave_service sh`
3. `ls src/master_volume/`

hoge.txt が存在していることが確認できると思います。

以上が設定と動作確認となります。

もし、あなたの環境の親の docker-compose で volume を定義したあと volume 名を確認するときは `docker volume ls` コマンドで確認できます。
今回のケースで上記のコマンドを実行すると

```
DRIVER              VOLUME NAME
...
local               master_docker-compose_master_volume
...
```

のように表示されます。
この表示された VOLUME NAME を子の関係の docker-compose.yml に設定すれば大丈夫です。

## network 共有設定と動作確認

続いて network になります。
volume と同様に 2 つの docker-compose は動かしている前提です。

network の設定では親の docker-compose.yml の設定必要ありません。
子の docker-compose.yml の設定のみです。

[shared-docker-compose-example/slave_docker-compose/docker-compose.yml](https://github.com/furuuchitakahiro/shared-docker-compose-example/blob/master/slave_docker-compose/docker-compose.yml#L19-L22) ( 子の docker-compose.yml )
19 ~ 22 行目

```yml
networks:
  default:
    external:
      name: master_docker-compose_default
```

この設定で親のネットワークに接続できます。
試しに、slave_service コンテナを操作して確認してみましょう。

1. `cd shared-docker-compose-example/slave_docker-compose`
2. `docker-compose exec slave_service sh`
3. `ping master_service`

以下のように表示されるはずです。

```
PING master_service (172.29.0.2): 56 data bytes
64 bytes from 172.29.0.2: seq=0 ttl=64 time=0.145 ms
64 bytes from 172.29.0.2: seq=1 ttl=64 time=0.160 ms
64 bytes from 172.29.0.2: seq=2 ttl=64 time=0.160 ms
64 bytes from 172.29.0.2: seq=3 ttl=64 time=0.242 ms
...
```

親と子の間で通信できていることが確認できました。

以上が設定と動作確認となります。

もし、あなたの環境の親の network を確認する際は `docker network ls` コマンドで確認できます。
今回のケースで上記のコマンドを実行すると

```
NETWORK ID          NAME                            DRIVER              SCOPE
...
04cc93553967        master_docker-compose_default   bridge              local
...
```

のように表示されます。
この表示された NAME を子の関係の docker-compose.yml に設定すれば大丈夫です。

**注意点として docker-compose の network を共有する際は各 docker-compose.yml のコンテナの host 名に気をつけましょう。**

# さいごに

いかがでしたでしょうか？
以上が docker-compose 間で volume と network を共有する知見でした。
お役に立てれば幸いです。