別々のdocker-compose環境同士でネットワーク間を連携する

2022/08/21に公開

リポジトリを別々に分けていて、それぞれのリポジトリにdocker-compose.ymlがある場合が多いと思います。

それぞれでdocker-composeを立ち上げれば、当然異なるdockerネットワークとなります。
しかし、場合によっては以下の画像のように、その2つのdockerネットワーク間で通信をしたい場合もあると思います。

フロントエンドとバックエンドでリポジトリを分け、それぞれのコンテナ間でAPI通信をするためにも、フロントエンドからバックエンドにHTTPリクエストを送れるようにしなければいけません。

外向きの通信をするコンテナに対して新たなネットワークを設定

今回はフロントエンドからバックエンドに対してHTTPリクエストを送るようにします。

今回はexternalというネットワークを作成して設定します。docker-compose.ymlの一番下に以下を記述します。

docker-compose.yml
networks:
  external:
    external: true

コンテナ側のnetworksに繋ぐネットワークを記述します。ここでは新たに作成したネットワークのexternalを記述します。

repository_1/docker-compose.yml
version: '3'
services:
  front:
    build: .
    ports:
      - '3000:3000'
    networks:
      - external

  .....
  .....

networks:
  external:
    external: true

バックエンド側にも外向きのネットワークを接続を設定

次に通信を受けるバックエンド側にも外向きのネットワークを接続します。
これによりフロントエンド側からの通信を受け取ることができます。

バックエンドのコンテナにも先程作成したexternalを記述します。

repository_2/docker-compose.yml
version: '3'
services:
  backend:
    ....
    build: .
    ports:
      - '8000:8000'
    networks:
      - external

  .....
  .....

# 以下も追加する
networks:
  external:
    external: true

Dockerネットワークを作成する

以下のコマンドでdockerネットワークを作成できます。

$ docker network create external

externalネットワークが作成されたかどうかは以下で確認できます。externalネットワークが表示されれば、作成は成功です。

$ docker network ls|grep external
{container_id}   external           bridge    local

Dockerネットワークを確認する

次に実際に作成したexternalネットワークにコンテナが繋がっているかを確認します。

$ cd repository_1
$ docker-compose up -d 

$ cd repository_2
$ docker-compose up -d

docker network inspectコマンドで、Dockerネットワークの詳細が表示されます。

以下のコマンドでexternalネットワークに上記2つのbackendとfrontendのコンテナがあれば成功です。

$ docker network inspect external
[
	{
		"Name": "external",
		....
		"Containers": {
			# フロント側のコンテナ
			"408e6429979bd18ee5719e3589440a8c1cc8df2b15f634642bf7779e6ca8a9a9": {
				"Name": "frontend",
				"EndpointID": "a018492ee2fd5d7465cbccc850b7a9e5ad943f11188ab94d4db14503e33e7d91",
				"MacAddress": "02:42:ac:17:00:02",
				"IPv4Address": "172.23.0.2/16",
				"IPv6Address": ""
			},
			# バックエンド側のコンテナ
			"946f9de7a422c66a7b39536ceef592826fb3d21e5f80dd2ad3048eb1ac1263aa": {
				"Name": "backend",
				"EndpointID": "9379f10d542cf723f800e998cc3f7ba72765006bcff7b3474da7525f0b96f4f0",
				"MacAddress": "02:42:ac:17:00:03",
				"IPv4Address": "172.23.0.3/16",
				"IPv6Address": ""
			}
		},
		"Options": {},
		"Labels": {}
	}
]

externalネットワークのfrontendコンテナのIPアドレスが172.23.0.2、backendコンテナIPアドレスが172.23.0.3だということがわかります。

  • frontend: 172.23.0.2
  • backend: 172.23.0.3

ネットワークアドレスが172.23.0.0のネットワークだということもわかります。

コンテナ間で疎通確認を行う

次に実際にフロントエンドからバックエンド側に対して通信が行えるかを確認してみます。
上記で確認したbackendコンテナのIPは172.23.0.3です。このIPアドレスに対してpingを送ってみます。

$ cd repository_1
$ docker-compose exec frontend ping 172.23.0.3

PING 172.23.0.3 (172.23.0.3) 56(84) bytes of data.
64 bytes from 172.23.0.3: icmp_seq=1 ttl=64 time=0.076 ms
64 bytes from 172.23.0.3: icmp_seq=2 ttl=64 time=0.071 ms
64 bytes from 172.23.0.3: icmp_seq=3 ttl=64 time=0.103 ms
64 bytes from 172.23.0.3: icmp_seq=3 ttl=64 time=0.099 ms

pingの結果が返ってくれば成功です。

externalネットワーク内でコンテナのIPアドレスを固定する

docker network inspectで毎回IPアドレスを調べるのは面倒です。
そこで、コンテナに対して割り振られるIPアドレスを固定することができます。

次のコマンドでサブネットマスクとゲートウェイを固定したDockerネットワークを作成できます。
ここではネットワークアドレスを192.168.1.0/24、ゲートウェイを192.168.1.1に設定します。

### subnet, gatewayを指定する
$ docker network create external-api --subnet=192.168.1.0/24 --gateway=192.168.1.1

次にdocker-compose.ymlに以下を記述することで、任意のIPアドレスをコンテナに割り振ることができます。

networks:
  # 任意のIPアドレスを設定する
  - external:
      ipv4_address: 192.168.1.2

ファイル全体では以下のようになります。

repository_1/docker-compose.yml
version: '3'
services:
  front:
    build: .
    ports:
      - '3000:3000'
    networks:
      # 任意のIPアドレスを設定する
      - external:
          ipv4_address: 192.168.1.2

  .....
  .....

networks:
  external:
    external: true

バックエンド側にもコンテナにIPアドレスを割り振ります。

repository_2/docker-compose.yml
version: '3'
services:
  backend:
    ....
    build: .
    ports:
      - '8000:8000'
    networks:
      - external:
          ipv4_address: 192.168.1.3

  .....
  .....

# 以下も追加する
networks:
  external:
    external: true

docker network inspectコマンドで確認してみると、先程指定した任意のIPアドレスがコンテナに割り振られていることがわかります。

$ docker network inspect external
[
	{
		"Name": "external",
		....
		"Containers": {
			# フロント側のコンテナ
			"408e6429979bd18ee5719e3589440a8c1cc8df2b15f634642bf7779e6ca8a9a9": {
				"Name": "frontend",
				"EndpointID": "a018492ee2fd5d7465cbccc850b7a9e5ad943f11188ab94d4db14503e33e7d91",
				"MacAddress": "02:42:ac:17:00:02",
				"IPv4Address": "192.168.1.2/24",
				"IPv6Address": ""
			},
			# バックエンド側のコンテナ
			"946f9de7a422c66a7b39536ceef592826fb3d21e5f80dd2ad3048eb1ac1263aa": {
				"Name": "backend",
				"EndpointID": "9379f10d542cf723f800e998cc3f7ba72765006bcff7b3474da7525f0b96f4f0",
				"MacAddress": "02:42:ac:17:00:03",
				"IPv4Address": "192.168.1.3/16",
				"IPv6Address": ""
			}
		},
		"Options": {},
		"Labels": {}
	}
]

Discussion