複数docker-compose間での通信
Dockerを用いた開発において、複数のサービスについて各々docker-compose.ymlを作成するケースがある。マイクロサービスの枠組みではこれらのサービス間での通信が必要であるが、ローカル環境において通信に手間取ったのでメモ。
状況
- ローカルにて、別々の
docker-compose.yml
でサービスAとサービスBを立ち上げたところhttp://127.0.0.1
で通信が取れない。 - Dockerコンテナで独立したネットワークが作成され、docker-composeによってコンテナ間を接続するネットワークが作成される。しかしdocker-composeを複数展開すると、デフォルトではdocker-compose間を接続するネットワークが存在しないため通信できない。
解決法
以下のコマンドでshared_network
という名前の共有ネットワークを作成する。このときCIDR形式でサブネットの指定をしていることに注意。
$ docker network create shared_network --driver bridge --subnet 172.31.0.0/24
ここではdjangoとnginxでAPIを立ち上げる状態を仮定する。docker-compose.yml
は以下のように記述する。最上位のnetworks
にてこのサービスが接続するネットワークを指定する。
各サービスのnetworks
にて接続する共有ネットワークshared_network
を指定し、さらに固定のipv4アドレスを割り当てる。この時IPアドレスは共有ネットワーク作成時のサブネットの範囲内であることと、他のサービスのIPアドレスと競合しないことに注意する。
サービスAとサービスBは同じローカル環境で起動しているので、ポートの衝突を避けるために以下では8000
と8080
に設定している。
サービスA
docker-compose.yml
version: '3.8' services: web: build: . command: "python manage.py runserver 8000" networks: shared_network: ipv4_address: 172.31.0.2 nginx: image: nginx:1.17.7 tty: true ports: - 8000:80 networks: shared_network: ipv4_address: 172.31.0.3 depends_on: - web volumes: postgres_data: web: driver: local networks: shared_network: external: true
サービスBに関しても同様.サービスAも含めたネットワーク全体で,IPアドレスが競合しないように注意する.
サービスB
docker-compose.yml
version: '3.8' services: web: build: . command: "python manage.py runserver 8080" container_name: web networks: shared_network: ipv4_address: 172.31.0.5 nginx: image: nginx:1.17.7 tty: true container_name: nginx depends_on: - web ports: - 8080:80 networks: shared_network: ipv4_address: 172.31.0.6 volumes: web: driver: local networks: shared_network: external: true
するとサービスAからサービスBに向けて、たとえば以下のリクエストで通信が取れるようになる。
import json import requests url = 'http://172.31.0.6' # サービスBのnginx response = requests.post( url, data=json.dumps(request_data), headers={'Content-Type': 'application/json'} )