Python | DevOps・運用:Docker network

Python Python
スポンサーリンク

Docker networkって何?一言でいうと「コンテナ同士をつなぐ“専用LAN”」

Docker network は、コンテナ同士をつなぐための「仮想ネットワーク」です。
同じネットワークに属するコンテナは、お互いを IP や名前で呼び合えます。
逆に、ネットワークが違えば、基本的にはお互い見えません。

Python の世界だと、

FastAPI コンテナから DB コンテナに接続する
Web アプリから Redis に接続する

といった場面で、Docker network が必ず関わってきます。

「どのコンテナが、どのコンテナと話せるのか」を決めるのが Docker network です。


まずはイメージ:FastAPI と PostgreSQL を同じネットワークに乗せる

docker-compose での典型的な例

よくある docker-compose.yml を思い出してみます。

version: "3.9"

services:
  web:
    build: .
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=postgresql://myuser:mypass@db:5432/mydb
    depends_on:
      - db

  db:
    image: postgres:16
    environment:
      - POSTGRES_USER=myuser
      - POSTGRES_PASSWORD=mypass
      - POSTGRES_DB=mydb
YAML

ここには networks: を書いていませんが、
実は docker-compose が自動で「1つのネットワーク」を作って、webdb をそこに参加させています。

その結果、

web から db という名前で PostgreSQL に接続できる
DATABASE_URL@db:5432db は、サービス名そのもの

という状態になります。

「同じ compose ファイルの services にいるコンテナは、同じネットワークにいて、サービス名で名前解決できる」
これがまず押さえておきたい基本ルールです。


重要ポイント1:コンテナ同士は「サービス名(コンテナ名)」でつながる

なぜ localhost ではなく db なのか

初心者が最初にハマるポイントがここです。

FastAPI の設定で、ついこう書きたくなります。

DATABASE_URL = "postgresql://myuser:mypass@localhost:5432/mydb"
Python

でも、コンテナの中から見た localhost は「そのコンテナ自身」です。
FastAPI コンテナから見た localhost は FastAPI コンテナであって、PostgreSQL コンテナではありません。

だから、Docker network を使うときは、

localhost ではなく、DB コンテナの名前(サービス名)を書く

必要があります。

さっきの compose なら、

DATABASE_URL = "postgresql://myuser:mypass@db:5432/mydb"
Python

が正解です。

ここでの db は、Docker network の中で解決される「ホスト名」です。
DNS みたいなものが、Docker の中にあるイメージです。


重要ポイント2:ネットワークを分けると「誰と誰が話せるか」を制御できる

明示的にネットワークを定義してみる

docker-compose では、ネットワークを自分で定義することもできます。

version: "3.9"

services:
  web:
    build: .
    ports:
      - "8000:8000"
    networks:
      - app-net
    environment:
      - DATABASE_URL=postgresql://myuser:mypass@db:5432/mydb

  db:
    image: postgres:16
    networks:
      - app-net

networks:
  app-net:
    driver: bridge
YAML

ここでは、

app-net という名前のネットワークを定義
webdb をそのネットワークに参加させる

ということをしています。

結果として、

webdb はお互いに見える
app-net に参加していないコンテナからは見えない

という状態になります。

ネットワークを分ける意味

ネットワークを分けると、
「このコンテナは、このグループの中のコンテナとだけ話せる」
という境界線を引けます。

例えば、

外向きの Nginx コンテナは「public-net」と「app-net」の両方に参加
アプリコンテナは「app-net」にだけ参加
DB コンテナも「app-net」にだけ参加

とすると、

外から直接 DB にアクセスされることはなく、
Nginx → アプリ → DB という経路だけが許される、という構成にできます。

DevOps・運用の観点では、「ネットワークで分離する」はセキュリティの基本テクニックです。
Docker network は、その「分離」をコンテナ単位でやるための仕組みです。


重要ポイント3:ホストとの通信とコンテナ同士の通信を分けて考える

ports は「ホストとコンテナの橋」

compose の ports は、ホストとコンテナの間の話です。

services:
  web:
    ports:
      - "8000:8000"
YAML

これは、

ホストの 8000 番ポート
コンテナの 8000 番ポート

をつなぐ、という意味です。

ブラウザから http://localhost:8000 にアクセスすると、
Docker が「ホストの 8000 → web コンテナの 8000」に転送してくれます。

これは Docker network とは別のレイヤーの話です。
Docker network は「コンテナ同士」、ports は「ホストとコンテナ」と覚えると整理しやすいです。

コンテナ同士の通信には ports はいらない

よくある勘違いが、

「web から db にアクセスするには、db に ports: "5432:5432" が必要」

と思ってしまうことです。

コンテナ同士の通信には、ports は不要です。
同じネットワークにいて、コンテナ内でポートが開いていれば、それで十分です。

ports は「ホストから見えるようにするための穴」なので、
内部だけで完結する DB には、本番では ports を開けない方が安全です。


重要ポイント4:ネットワークを意識すると「本番に近いローカル環境」が作りやすくなる

ローカルでも「本番と同じ名前」でつなぐ

本番環境で、

DATABASE_URL=postgresql://myuser:mypass@db:5432/mydb

のように設定しているなら、
ローカルの docker-compose でも同じように @db:5432 でつなぐと、
環境差が減ります。

ローカルでは localhost、本番では db.internal みたいに変えてしまうと、
設定の切り替えやバグの原因になります。

Docker network を使えば、
「どの環境でも、アプリから見える DB のホスト名は db
という世界を作れます。

CI でも同じネットワーク構成を再現できる

GitHub Actions などの CI でも、
docker-compose を使ってテスト環境を立ち上げることができます。

そのとき、

アプリコンテナ
DB コンテナ

を同じネットワークに乗せて、
アプリからは db で接続する、という構成にしておけば、

ローカル
CI
本番

で「ネットワークの前提」が揃います。

DevOps 的には、「環境ごとの違いを減らす」ことがとても重要で、
Docker network はそのための土台になります。


初心者向けの練習ステップ

ステップ1:FastAPI + PostgreSQL を compose で立てて、@db でつなぐ

実際に、

DATABASE_URL=postgresql://myuser:mypass@db:5432/mydb

で FastAPI から DB に接続してみる。
localhost ではなく db を使う感覚を体で覚える。

ステップ2:ネットワークを明示的に定義してみる

networks: を自分で書いて、

webdb を同じネットワークに乗せる
別のサービスを別ネットワークに分けてみる

などを試して、「誰と誰が話せるか」を意識してみる。


まとめ(Docker network は「コンテナ同士の世界を区切り、名前でつなぐための仮想LAN」)

初心者目線で整理すると、Docker network はこういうものです。

同じネットワークに属するコンテナ同士は、サービス名(コンテナ名)でお互いに通信でき、docker-compose では「同じ services にいるコンテナは同じネットワークに乗る」のが基本。
localhost ではなく db のようなサービス名で接続することで、ローカル・CI・本番で同じ接続文字列を使えるようになり、ネットワークを分けることで「誰と誰が話せるか」を制御できる。

タイトルとURLをコピーしました