2026年8月12日
2026年8月12日
Docker Composeのネットワーク設定を詳しく解説|分離・固定IP・外部ネットワーク接続まで
Docker Composeは、何も書かなくてもプロジェクトごとに専用のブリッジネットワークを作り、サービス名で互いに通信できるようにします。そのうえで networks を明示的に定義すると、「DBには外から届かない構成」「別のcomposeプロジェクトとの接続」「社内LANと重ならないサブネット」といった制御ができるようになります。この記事では、デフォルトの動きから、ネットワークの分離、IPAMでのサブネット指定、外部ネットワークの共有、つまずきやすい点の調べ方までを順に説明します。
コマンドはCompose v2(docker compose)を前提にしています(2026年10月現在)。Compose v2ではファイル先頭の version: キーは使われておらず、書いても警告が出るだけなので、この記事の例では省いています。
デフォルトで作られるネットワークと名前解決
docker compose up を実行すると、Composeは {プロジェクト名}_default という名前のブリッジネットワークを作り、networks を指定していないサービスをすべてそこにつなぎます。プロジェクト名は、指定がなければcomposeファイルのあるディレクトリ名です。-p オプション、環境変数 COMPOSE_PROJECT_NAME、またはcomposeファイルのトップレベルの name: で変えられます。ディレクトリ名に依存するとリポジトリを別名でcloneしたときにネットワーク名まで変わるため、運用するプロジェクトでは name: を書いておくと扱いやすくなります。
name: mysite
services:
wordpress:
image: wordpress:php8.3-apache
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wp
WORDPRESS_DB_PASSWORD: your-db-password
WORDPRESS_DB_NAME: wordpress
ports:
- "8080:80"
db:
image: mysql:8.4
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wp
MYSQL_PASSWORD: your-db-password
MYSQL_ROOT_PASSWORD: your-root-password
この構成では mysite_default が作られ、wordpress コンテナから db というホスト名でMySQLに届きます。名前解決をしているのは、ユーザー定義ネットワーク上のコンテナに組み込まれるDockerの内蔵DNS(コンテナ内では 127.0.0.11)です。サービス名のほか、コンテナ名でも引けます。
ここで押さえておきたいのは、コンテナ同士の通信に ports は要らないという点です。ports はホスト側にポートを公開する設定で、同じネットワーク内では db:3306 のようにコンテナ側のポートへ直接つながります。DBに ports: - "3306:3306" を書くと、サーバーのグローバルIPからMySQLが見えてしまうことがあるので、外から使う予定がなければ書かないのが安全です。
networksを定義して通信経路を分ける
フロント側(リバースプロキシ)とバックエンド側(アプリ・DB)でネットワークを分けると、プロキシからDBへ直接届かない構成にできます。トップレベルの networks でネットワークを宣言し、各サービスの networks で参加先を選びます。
name: mysite
services:
proxy:
image: nginx:1.27-alpine
ports:
- "80:80"
- "443:443"
networks:
- frontend
wordpress:
image: wordpress:php8.3-fpm
networks:
- frontend
- backend
db:
image: mysql:8.4
networks:
- backend
networks:
frontend:
backend:
internal: true
wordpress は両方に参加しているため、proxy からも db へも届きます。一方で proxy と db は共通のネットワークを持たないので、名前解決もできません。
internal: true を付けたネットワークは外部への経路を持たないため、db からインターネットへは出られなくなります。DBが外部と通信する必要がない構成なら、侵入されたときの被害範囲を狭められます。ただし wordpress も backend だけに参加させると、プラグインの更新や外部APIの呼び出しができなくなります。外に出る必要があるサービスは、外部へ出られるネットワーク(ここでは frontend)にも参加させてください。
networks を書いたサービスは default ネットワークには自動ではつながりません。既存の構成に一部だけ networks を足したとき、「さっきまで通じていたサービスに届かなくなった」という現象はたいていこれが原因です。必要であれば、サービスの networks に default を明示的に加えます。
エイリアスと固定IPの指定
サービス名とは別のホスト名で引けるようにしたいときは aliases を使います。たとえば、アプリの設定に mysql.internal というホスト名が書き込まれていて変えにくい場合などです。
services:
db:
image: mysql:8.4
networks:
backend:
aliases:
- mysql.internal
ipv4_address: 172.28.0.10
networks:
backend:
ipam:
config:
- subnet: 172.28.0.0/24
gateway: 172.28.0.1
ipv4_address で固定IPを割り当てるには、そのネットワークの ipam.config で subnet を定義しておく必要があります。サブネットを決めずに固定IPだけ書くと起動時にエラーになります。
とはいえ、固定IPが本当に必要になる場面は多くありません。コンテナ間の接続はサービス名で書けば再作成のたびにIPが変わっても影響を受けないため、まずは名前で解決する設計を考え、IPでしか指定できない外部機器のファイアウォール設定などに限って固定IPを使うのが無難です。
サブネットの衝突を避ける
Dockerはブリッジネットワークを作るたびに、デーモンの既定のアドレスプール(172.17.0.0/16 以降の 172.x 帯や 192.168.x 帯)から空いている範囲を割り当てます。このため、VPNや社内LANが同じ帯域を使っていると、ネットワークが作られた瞬間にサーバーへSSHが通らなくなる、特定の拠点からだけサイトが見えなくなる、といった障害が起こることがあります。
対処は二つあります。一つは上の例のように、composeファイルの ipam.config で衝突しないサブネットを明示する方法です。もう一つは、/etc/docker/daemon.json でデーモン全体のアドレスプールを変える方法です。
{
"default-address-pools": [
{ "base": "10.200.0.0/16", "size": 24 }
]
}
daemon.json を変更したら sudo systemctl restart docker で反映します。デーモンの再起動ではすべてのコンテナが止まるため、本番サーバーでは作業時間を決め、設定ファイルのバックアップを取ってから行ってください。既存のネットワークは作り直すまで古いサブネットのままです。
別のcomposeプロジェクトとネットワークを共有する
リバースプロキシを一つのcomposeで動かし、複数のサイトを別々のcomposeで動かす構成では、プロジェクトをまたいで通信させる必要があります。この場合は、どのプロジェクトにも属さないネットワークを先に作り、各composeから external: true で参照します。
docker network create proxy-net
# サイト側の compose.yaml
services:
wordpress:
image: wordpress:php8.3-fpm
networks:
- proxy-net
- default
networks:
proxy-net:
external: true
external: true のネットワークはComposeが作成も削除もしません。存在しない状態で up すると「network proxy-net declared as external, but could not be found」というエラーで止まるので、サーバー構築手順に docker network create を含めておきます。また docker compose down を実行しても外部ネットワークは残ります。
共有ネットワーク上ではサービス名が衝突しやすい点にも注意が必要です。複数のプロジェクトがどれも wordpress という名前のサービスを proxy-net に出していると、プロキシから wordpress を引いたときにどちらに届くか分かりません。プロジェクトごとに site-a-wp のような aliases を付け、プロキシ側の設定ではそのエイリアスを使うと混乱を避けられます。
network_modeでホストのネットワークを使う
network_mode を指定すると、ブリッジネットワークを使わない動作にできます。host はホストのネットワークをそのまま使うモード(Linuxのみ)、none はネットワークなし、service:サービス名 は別のサービスとネットワーク名前空間を共有するモードです。network_mode と networks は同時に指定できません。host ではポートの割り当てがホストと直接競合し、ports の指定も無視されるので、監視エージェントなど理由がはっきりしているものに限るのがよいでしょう。各モードの違いは関連記事で詳しく扱っています。
設定が効いているかを確かめる方法
ネットワーク関連の不具合は、「どのネットワークに誰がつながっているか」を実際に見ると原因が早く分かります。
# プロジェクトが作ったネットワークの一覧
docker network ls --filter label=com.docker.compose.project=mysite
# サブネットと参加しているコンテナの確認
docker network inspect mysite_backend
# コンテナの中から名前解決できるか
docker compose exec wordpress getent hosts db
# composeファイルが最終的にどう解釈されたか
docker compose config
docker network inspect の Containers 欄に目的のコンテナが出ていなければ、そのネットワークには参加していません。getent で名前が引けないのに inspect 上は参加している場合は、相手側がまだ起動していないか、depends_on だけでは起動完了を待たないために接続時点で準備ができていない可能性があります。Alpine系のイメージには getent がない場合があるので、その場合は nslookup db などで確認します。
composeファイルのネットワーク定義を変えたのに反映されないときは、docker compose down でネットワークごと削除してから docker compose up -d で作り直すと、意図どおりの状態から確認できます。down に -v を付けるとボリュームも消えるため、DBのデータを残したい場合は付けないでください。
まとめ
- Composeは
{プロジェクト名}_defaultを自動で作り、サービス名で名前解決できる。プロジェクト名はname:で固定すると扱いやすい。 - コンテナ間の通信に
portsは不要。DBのポートを公開しないだけで露出を減らせる。 networksでフロントとバックエンドを分け、外部に出る必要のないネットワークはinternal: trueにする。networksを書いたサービスはdefaultから外れる点に注意する。- 固定IPは
ipamでサブネットを定義したうえで使う。社内LANやVPNとの衝突はipamかdaemon.jsonのdefault-address-poolsで避ける。 - プロジェクトをまたぐ通信は、先に作ったネットワークを
external: trueで参照する。 - 不具合時は
docker network inspectとdocker compose configで実際の状態を確かめる。