Docker Network で複数の Docker Compose 環境を共有する

2023-01-29

複数のDocker Compose環境で通信を行いたい場合は共有するNetworkを設定する必要があります。

ここでは、redisのDBサーバーとPythonのwebサーバーを別のdocker-compose.ymlファイルで作成して Docker Networkの共有を行ってみます。

構成ファイル

ディレクトリの階層は以下のようにしました。

shell
1tree
2.
3├── db
4│   └── docker-compose.yml
5└── web
6 ├── Dockerfile
7 ├── app.py
8 ├── docker-compose.yml
9 └── requirements.txt

db/配下の docker-compose.ymlweb/配下のdocker-compose.yml`の2種類があります。

動作確認

各ディレクトリに入り、以下のコマンドをそれぞれ実行します。

今回の構成の場合はdbがwebに依存する作りになっており、webの方からコンテナを起動する必要があります。

shell
1cd web/
2docker compose up
shell
1cd db/
2docker compose up

ブラウザで http://localhost:8000/ にアクセスすると、

Hello World! I have been seen 1 times. のテキストが表示されると正常に動作していることになります。

アクセス数によって、数値がインクリメントされていきます。

作成されるnetwork

以下のネットワークが生成されます。

shell
1docker network ls
2d51b3d134b41 db bridge local
37180169bae5f db_default bridge local
4c6fc31adbea3 web_default bridge local
shell
1docker network inspect db
2[
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

yaml
1version: '3.9'
2services:
3 redis:
4 image: 'redis:alpine'
5 networks:
6 - default
7 - db
8networks:
9 db:
10 external: true
11 name: '${NETWORK_ID}'
yaml
1networks:
2 - default
3 - db

の部分でトップレベルのnetworkキー、ここでは、

yaml
1networks:
2 db:
3 external: true
4 name: '${NETWORK_ID}'

の部分のエントリを参照しています。

externaltrueにした場合はこの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

Dockerfile
1FROM python:3.7-alpine
2WORKDIR /code
3ENV FLASK_APP=app.py
4ENV FLASK_RUN_HOST=0.0.0.0
5RUN apk add --no-cache gcc musl-dev linux-headers
6COPY requirements.txt requirements.txt
7RUN pip install -r requirements.txt
8EXPOSE 5000
9COPY . .
10CMD ["flask", "run"]
yaml
1version: '3.9'
2services:
3 web:
4 build: .
5 ports:
6 - '8000:5000'
7 networks:
8 - default
9 - db
10networks:
11 db:
12 name: db

dbという名前のネットワークを作成するため、トップレベルのnetworksエントリにネットワークの設定があります。

このネットワークをredis側より参照します。

web/app.py

python
1import time
2
3import redis
4from flask import Flask
5
6app = Flask(__name__)
7cache = redis.Redis(host='redis', port=6379)
8
9def get_hit_count():
10 retries = 5
11 while True:
12 try:
13 return cache.incr('hits')
14 except redis.exceptions.ConnectionError as exc:
15 if retries == 0:
16 raise exc
17 retries -= 1
18 time.sleep(0.5)
19
20@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

txt
1flask
2redis

その他、Webサーバーの実装については本題とずれるため解説しません。

ちなみにnetworkの設定がないと、webサーバーがredisに接続できず、ブラウザ側では500エラーとなります。

コンソールには、以下のようなエラーメッセージが表示されます。

shell
1web-web-1 | redis.exceptions.ConnectionError: Error -2 connecting to redis:6379. Name does not resolve.

Tech Blog

avatar

ソフトウェアエンジニア。1989年生まれ大阪府岸和田市在住のフリーランス。PHP、バックエンド開発が得意。テニス、フットサル、だんじり、ケツメイシ、競馬、プログラミングが好き!最近はWebフロントエンド沼にハマってます!

Copyright © 2023. Junpeko5's Tech Blog