第27章:Compose networks:内部ネットワークで閉じ込める🕸️🔒
この章は「同じマシン上に“部屋”を作って、通していい通信だけ通す」がゴールです😊 Docker Compose のネットワークは、ざっくり言うと コンテナ同士が話せる“グループ”。ここを分けると、被害半径が一気に小さくなります🛡️✨
この章でできるようになること✅
- 「公開していい入口」だけを外に出す🚪🌐
- DB/Redis みたいな中身は 内部ネットワークに閉じ込める🍱🔐
- 「AはBに話していいけど、Cには話させない」を Compose で表現できる🧩
- “うっかり全部つながってた事故”をネットワーク設計で防げる😇💥
まず超重要な3点だけ🧠✨
1) Compose はデフォで「全部つながる」😺
Compose は、何も書かないと アプリ用のネットワークを1つ作って、各サービスをそこに参加させます。 だからサービス同士は基本「届く」し、サービス名で名前解決できます📡✨ (Docker Documentation)
つまり…
apiからdbにdb:5432で繋がっちゃう、が標準状態です(便利だけど、隔離としては雑になりやすい)😅
2) 「ports」は“外へのドア”、ネットワークは“部屋の中の通路”🚪🕸️
- ネットワーク:コンテナ同士が話すための通路
- ports:ホスト(=あなたのPC)や外部から入るためのドア
ports はホスト⇄コンテナのポート対応を作ります。何も指定しないと 0.0.0.0(全IF)にバインドしがちなので要注意⚠️ (Docker Documentation)
さらに Docker 側も「ポート公開はデフォだと危険寄り」ってハッキリ言ってます😱 (Docker Documentation)
👉 コツ:開発中は 127.0.0.1: を付けて 自分のPCだけに限定しよう🧯✨ (Docker Documentation)
3) 「internal: true」で“外部と切れたネットワーク”が作れる🔒
Compose は通常、ネットワークに外部接続性を持たせます。
internal: true にすると externally isolated network(外部から隔離されたネットワーク) を作れます🧊 (Docker Documentation)
「DBは外に出なくていい」「勝手に外へ通信してほしくない」みたいな層に刺さります🎯
ネットワーク設計の型:3層に分ける🍰✨
ここからは“よくある個人開発の型”でいきます👇
- edge:外(ホスト)に公開する“入口”だけ
- app_net:入口 ⇄ アプリの通路
- data_net:アプリ ⇄ DB/Redis の通路(ここを
internal: trueで閉じる)🔒
そして大事なのがこれ👇 同じネットワークを共有してないサービス同士は、基本的に会話できない(=壁ができる)🧱✨ Docker Docs でも「proxy は db とネットワークを共有しないから隔離される」例が出ています。 (Docker Documentation)
ハンズオン:閉じ込めネットワークを作って“壁”を体感しよう🧪🧱
0) 構成イメージ🗺️
- ブラウザ →
proxy(入口) proxy→api(中)api→redis(奥)proxyはredisに届かない(壁!)🧱
1) compose.yaml を作る📝
プロジェクト直下に compose.yaml を作って、これをコピペ👇
services:
proxy:
image: nginx:alpine
ports:
- "127.0.0.1:8080:80"
volumes:
- ./proxy/nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- api
networks:
- edge
- app_net
api:
image: traefik/whoami:latest
networks:
- app_net
- data_net
redis:
image: redis:alpine
networks:
- data_net
# デバッグ用(必要な時だけ起動して疎通チェックする)
debug_app:
image: curlimages/curl:latest
command: ["sleep", "infinity"]
networks:
- app_net
profiles: ["debug"]
debug_data:
image: curlimages/curl:latest
command: ["sleep", "infinity"]
networks:
- data_net
profiles: ["debug"]
networks:
edge: {}
app_net: {}
data_net:
internal: true
ポイント💡
proxyだけportsを持つ(入口だけ外へ)🚪redisはportsなし(ホストから直接入れない)🙅♂️proxyはdata_netに入れてない(DB層に壁)🧱data_netはinternal: trueで“外部隔離”🔒 (Docker Documentation)- 追加ネットワークは「サービス側で許可しないと繋がらない」ルール🧩 (Docker Documentation)
2) proxy/nginx.conf を作る🧷
proxy フォルダを作って、その中に nginx.conf を作成👇
server {
listen 80;
location / {
proxy_pass http://api:80;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
ここで api って書けるのが Compose の気持ちよさです😆
同じネットワーク上だと サービス名で発見可能だから! (Docker Documentation)
3) 起動してみる▶️
docker compose up -d
docker compose ps
4) 動作確認👀✨
ブラウザ or curl で👇
curl http://127.0.0.1:8080/
whoami の情報が返ってきたらOK🎉(proxy→api ルートが通ってる)
“壁”を確認するデバッグ実験🧱🧪
実験A:app_net から redis を見ようとして失敗する(壁がある)❌
デバッグ用コンテナを起動して中へ👇
docker compose --profile debug up -d debug_app
docker compose exec debug_app sh
中で redis を引いてみる👇
## DNS解決できない or 接続できない(proxy層と同じで data_net にいないから)
curl -v redis:6379
**「同じネットワークを共有してないと届かない」**を体感できたら勝ちです🏆 この“共有してないから隔離される”考え方が核です🔥 (Docker Documentation)
実験B:data_net 側なら redis が見える✅
docker compose --profile debug up -d debug_data
docker compose exec debug_data sh
## こっちは data_net にいるので redis に届く(疎通そのものは確認できる)
curl -v redis:6379
Redis はHTTPじゃないのでレスポンスは期待どおりじゃないけど、接続はできるはずです👍 「見える/見えないの境界」がネットワークで決まるのが大事✨
もっと気持ちよく確認したい人へ😎
redis-cliが入ったイメージ(公式のredisなど)を“デバッグ専用”で使うのもアリ!
超よくある事故パターン3つ😇💣(ここだけ覚えて)
事故1:DBに ports を付けちゃう🫠
「とりあえず繋がらないから 6379:6379 で出しちゃえ!」
→ これ、最小公開の真逆です😱
ports は外へのドア。必要な入口以外はドアを付けない🚪✂️
(ports はホスト側に公開するための機能)(Docker Documentation)
事故2:全部同じネットワークに入れちゃう🙈
便利なんだけど、隔離が消えます。 “壁”が欲しいところは ネットワークを分けて、共有しないが基本🧱✨ (Docker Documentation)
事故3:ports を 0.0.0.0 で全開放しちゃう🌐😱
ports のホストIPを省略すると全IFにバインドされることがあるので注意⚠️ (Docker Documentation)
開発中はこう👇(自分のPCだけに限定)
ports:
- "127.0.0.1:8080:80"
「localhost を付けるとホストだけアクセス可能」という注意喚起も公式にあります🧯 (Docker Documentation)
AI拡張を使うときの“ネットワーク視点”の安全ルール🤖🛡️
AIが提案してきた Compose 差分を見たら、まずここだけチェック✅
ports:が増えてない?(特に DB/Redis に付いてない?)🚪⚠️- 追加した
networks:が“全部同じ”になってない?🕸️💥 internal: trueを外してない?🔒😱- 「とりあえず privileged」「とりあえず docker.sock」みたいな“危険カード”が混ざってない?🗑️🔥
AIは速いけど、隔離の設計判断は人間の役目にすると事故が減ります🙂✨
仕上げ:この章のチェックリスト✅🕔
- 外に出すのは入口だけ(基本は
proxy/webだけ)🚪 - DB/Redis は
portsなし(内部ネットワークに閉じ込め)🍱 - “話していい組”だけ同じネットワークに入れる🧱
- データ層は
internal: trueを検討🔒 (Docker Documentation) - ネットワーク名やサービス名で繋ぐ(同一ネットワーク上で発見可能)📛📡 (Docker Documentation)
次は第28章で、この“境界”をさらに強くして DB/Redis を内部専用に固定しつつ、「開発用/テスト用の分離」もやっていきます🧪🔐✨