複数のDocker Compose環境で通信を行いたい場合は共有するNetworkを設定する必要があります。
ここでは、redisのDBサーバーとPythonのwebサーバーを別のdocker-compose.yml
ファイルで作成して Docker Networkの共 有を行ってみます。
ディレクトリの階層は以下のようにしました。
shell1tree2.3├── db4│ └── docker-compose.yml5└── web6 ├── Dockerfile7 ├── app.py8 ├── docker-compose.yml9 └── requirements.txt
db/配下の docker-compose.yml
とweb/配下の
docker-compose.yml`の2種類があります。
各ディレクトリに入り、以下のコマンドをそれぞれ実行します。
今回の構成の場合はdbがwebに依存する作りになっており、webの方からコンテナを起動する必要があります。
shell1cd web/2docker compose up
shell1cd db/2docker compose up
ブラウザで http://localhost:8000/ にアクセスすると、
Hello World! I have been seen 1 times.
のテキストが表示されると正常に動作していることになります。
アクセス数によって、数値がインクリメントされていきます。
以下のネットワークが生成されます。
shell1docker network ls2d51b3d134b41 db bridge local37180169bae5f db_default bridge local4c6fc31adbea3 web_default bridge local
shell1docker network inspect db2[3 {4 "Name": "db",5 "Id": "d51b3d134b417dbba29755e0a3ee4a2c6e7e2806317aae3b24027ac1bf48c9b7",6 "Created": "2023-01-29T13:09:55.622193753Z",7 "Scope": "local",8 "Driver": "bridge",9 "EnableIPv6": false,10 "IPAM": {11 "Driver": "default",12 "Options": null,13 "Config": [14 {15 "Subnet": "172.23.0.0/16",16 "Gateway": "172.23.0.1"17 }18 ]19 },20 "Internal": false,21 "Attachable": false,22 "Ingress": false,23 "ConfigFrom": {24 "Network": ""25 },26 "ConfigOnly": false,27 "Containers": {28 "1e7a6fab6ea0930f3861b1f211300a899bdc9b04b59ca3f429fe53dd3cd5a127": {29 "Name": "db-redis-1",30 "EndpointID": "d3f230572877316ad5b31d86a6aa8f5184f1c60527716e3c2e9249fb61e5b2ab",31 "MacAddress": "02:42:ac:17:00:03",32 "IPv4Address": "172.23.0.3/16",33 "IPv6Address": ""34 },35 "e4416696d5bf59822bf15deb780a0d11b7b9e2d3f55e82fbbbb83b4eef078d1b": {36 "Name": "web-web-1",37 "EndpointID": "c3f5d8b0627b19e2c18f76293bb730c4c8baf596b2afcb6990338627c943fa10",38 "MacAddress": "02:42:ac:17:00:02",39 "IPv4Address": "172.23.0.2/16",40 "IPv6Address": ""41 }42 },43 "Options": {},44 "Labels": {45 "com.docker.compose.network": "db",46 "com.docker.compose.project": "web",47 "com.docker.compose.version": "2.13.0"48 }49 }50]
Containers の中にデフォルトで生成されるネットワークが含まれていることが確認できます。
db/docker-compose.yml
yaml1version: '3.9'2services:3 redis:4 image: 'redis:alpine'5 networks:6 - default7 - db8networks:9 db:10 external: true11 name: '${NETWORK_ID}'
yaml1networks:2 - default3 - db
の部分でトップレベルのnetworkキー、ここでは、
yaml1networks:2 db:3 external: true4 name: '${NETWORK_ID}'
の部分のエントリを参照しています。
external
をtrue
にした場合はこのdocker-compose.ymlで管理しない外部のネットワークを利用します。
NETWORK_IDという変数をname
に設定していて、外部の実装に依存しないようにしています。
https://docs.docker.jp/compose/compose-file/index.html#external https://docs.docker.jp/compose/compose-file/index.html#id51
web/Dockerfile
Dockerfile1FROM python:3.7-alpine2WORKDIR /code3ENV FLASK_APP=app.py4ENV FLASK_RUN_HOST=0.0.0.05RUN apk add --no-cache gcc musl-dev linux-headers6COPY requirements.txt requirements.txt7RUN pip install -r requirements.txt8EXPOSE 50009COPY . .10CMD ["flask", "run"]
yaml1version: '3.9'2services:3 web:4 build: .5 ports:6 - '8000:5000'7 networks:8 - default9 - db10networks:11 db:12 name: db
db
という名前のネットワークを作成するため、トップレベルのnetworksエントリにネットワークの設定があります。
このネットワークをredis側より参照します。
web/app.py
python1import time23import redis4from flask import Flask56app = Flask(__name__)7cache = redis.Redis(host='redis', port=6379)89def get_hit_count():10 retries = 511 while True:12 try:13 return cache.incr('hits')14 except redis.exceptions.ConnectionError as exc:15 if retries == 0:16 raise exc17 retries -= 118 time.sleep(0.5)1920@app.route('/')21def hello():22 count = get_hit_count()23 return 'Hello World! I have been seen {} times.\n'.format(count)24
web/requirements.txt
txt1flask2redis
その他、Webサーバーの実装については本題とずれるため解説しません。
ちなみにnetworkの設定がないと、webサーバーがredisに接続できず、ブラウザ側では500エラーとなります。
コンソールには、以下のようなエラーメッセージが表示されます。
shell1web-web-1 | redis.exceptions.ConnectionError: Error -2 connecting to redis:6379. Name does not resolve.