言語を切り替える
テーマを切り替える

Docker コンテナ間通信の実践:Web と DB を名前でつなぐ正しい方法

金曜の午後 3 時、ローカル開発環境のコンテナ化を仕上げようとしていました。MySQL コンテナは起動、Node.js アプリコンテナも動いている——あとはつなぐだけ、と思っていました。ブラウザを更新すると 500 エラー。ログには「Connection refused」が並んでいます。

両方のコンテナが動いているのに、なぜ? MySQL コンテナ名で ping すると「unknown host」。IP で試すと通る。アプリも DB に接続できました。ほっとしてコミットし、帰宅。

月曜に戻ると悲劇です。アプリがまた落ちている。MySQL コンテナ再起動で IP が 172.17.0.2 から 172.17.0.3 に変わっていた。毎回再起動のたびに設定を直すのか——本当にきつかった。

同じ経験があるなら、この記事はあなた向けです。Docker のネットワークを一午後かけて調べ、コンテナ間通信の正しいやり方がわかりました。次を共有します。

  • コンテナ名で ping できない根本原因
  • デフォルトネットワークの制限
  • カスタムネットワークでの解決
  • 名前で相互アクセスする実践手順
  • 応用のコツとベストプラクティス

なぜコンテナ名で ping できないのか

Docker デフォルトネットワークの制限

原因は Docker のデフォルトネットワーク設定にあります。ネットワークを指定せず起動すると、コンテナは自動的にデフォルトの bridge ネットワーク(docker0 ブリッジ)に接続されます。

このデフォルトネットワークには大きな制限があります。IP アドレス通信のみで、コンテナ名解決に非対応です。

つまりデフォルトネットワークでは:

  • ✅ IP で他コンテナにアクセスできる(例:ping 172.17.0.2
  • ❌ コンテナ名ではアクセスできない(例:ping mysql-container は失敗)

なぜか。デフォルトネットワークには組み込み DNS がないからです。連絡先帳のない携帯のように、番号(IP)は覚えられるが名前(コンテナ名)では相手を特定できません。

さらに厄介なのは、コンテナ再起動のたびに Docker が IP を再割り当てすることです。今日 172.17.0.2 で MySQL に繋がっても、明日再起動後は 172.17.0.3 かもしれず、アプリ設定の IP は無効になります。

コマンドで確認しました:

# MySQL コンテナ起動(デフォルトネットワーク)
docker run -d --name mysql-demo \
  -e MYSQL_ROOT_PASSWORD=123456 \
  mysql:8.0

# ネットワーク確認用 busybox コンテナ
docker run -it --name test-box busybox sh

# test-box 内で MySQL コンテナ名を ping
/ # ping mysql-demo
ping: bad address 'mysql-demo'  # ← 名前解決失敗

# MySQL の IP を確認
docker inspect mysql-demo | grep IPAddress
# "IPAddress": "172.17.0.2"

# IP なら ping 成功
/ # ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.123 ms

コンテナ名では ping できず、IP だけ、という状態です。

古いチュートリアルでは --link が出てきます。Docker 初期の解決策です。

docker run --link mysql-demo:mysql -d my-app

これで my-app から「mysql」という名前で mysql-demo にアクセスできます。ただし Docker 公式は --link を推奨しておらず、将来バージョンで削除予定です。

非推奨の理由:

  1. 一方向接続:my-app → mysql のみ。逆方向は不可
  2. 保守が大変:コンテナが増えると --link 設定が複雑化
  3. 機能が限定的:柔軟なマルチコンテナネットワーク管理に不向き

まだ --link を使っているなら、新しい方法への移行をおすすめします。

カスタムネットワーク:コンテナ間通信の正しい方法

カスタムネットワークのメリット

Docker 1.12 以降の docker network が公式推奨のコンテナ間通信方式です。

カスタム bridge ネットワークの利点:

  1. 自動 DNS 解決:組み込み DNS がコンテナ名を IP に解決。「連絡先帳」付きネットワークのイメージです。

  2. ネットワーク分離:異なるカスタムネットワーク間のコンテナはデフォルトで隔離。フロント・バックエンド・DB を別ネットワークに分け、セキュリティを高められます。

  3. 保守性:再起動で IP が変わってもコンテナ名を使えば DNS が更新されるため、アプリ設定を変える必要がありません。

  4. マルチネットワーク:1 コンテナが複数ネットワークに参加でき、複雑なトポロジも可能です。

最初は Docker ネットワークが難しく感じますが、この 4 点がわかると一気に整理できます。

カスタムネットワークの作成

作成コマンドはシンプルです:

# 最もシンプル:名前だけ指定
docker network create my-app-net

# フルオプション版
docker network create \
  --driver bridge \         # ドライバ(デフォルトは bridge)
  --subnet 172.20.0.0/16 \  # カスタム IP レンジ(任意)
  --gateway 172.20.0.1 \    # カスタムゲートウェイ(任意)
  my-app-net                # ネットワーク名

多くの場合、最初のシンプルな方法で十分です。Docker が競合しない IP レンジを自動割り当てします。

作成後、詳細確認:

docker network inspect my-app-net

IP レンジ、ゲートウェイ、接続済みコンテナなどが確認できます。

コンテナをカスタムネットワークに参加させる

参加方法は 2 つあります。

方法 1:起動時に指定(推奨)

docker run -d \
  --name mysql-demo \
  --network my-app-net \  # ← 重要
  -e MYSQL_ROOT_PASSWORD=123456 \
  mysql:8.0

方法 2:実行中コンテナを後から接続

# 既に動いているコンテナがある場合
docker network connect my-app-net existing-container

起動時指定がおすすめです。方法 2 は既存コンテナを新ネットワークへ移行するとき向けです。

実践:Web アプリから MySQL に接続する

理論はここまで。Node.js アプリコンテナが MySQL DB コンテナに接続する手順を見ていきます。

シナリオ

目標:

  • MySQL コンテナ名 mysql-server、カスタムネットワーク上で稼働
  • Node.js アプリコンテナ名 node-app、同一ネットワーク
  • アプリは IP ではなくコンテナ名 mysql-server で DB に接続

実装手順

ステップ 1:カスタムネットワーク作成

docker network create my-app-net

ネットワーク ID が出力されれば成功です。

ステップ 2:MySQL コンテナを起動してネットワークに参加

docker run -d \
  --name mysql-server \
  --network my-app-net \
  -e MYSQL_ROOT_PASSWORD=my-secret-pw \
  -e MYSQL_DATABASE=myapp_db \
  mysql:8.0

パラメータ:

  • --name mysql-server:後で DB の host として使う名前
  • --network my-app-net:作成したネットワークへ接続
  • -e MYSQL_ROOT_PASSWORD:root パスワード
  • -e MYSQL_DATABASE:初期データベース作成

ステップ 3:アプリコンテナを起動

docker run -d \
  --name node-app \
  --network my-app-net \
  -p 3000:3000 \
  -e DB_HOST=mysql-server \
  -e DB_USER=root \
  -e DB_PASSWORD=my-secret-pw \
  -e DB_NAME=myapp_db \
  my-node-app:latest

DB_HOST=mysql-server に注目——IP ではなくコンテナ名です。

ステップ 4:アプリコードでコンテナ名を host に使う

Node.js の例:

const mysql = require('mysql2');

const connection = mysql.createConnection({
  host: process.env.DB_HOST,      // 'mysql-server'(コンテナ名)
  user: process.env.DB_USER,      // 'root'
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME
});

connection.connect((err) => {
  if (err) {
    console.error('データベース接続失敗:', err);
    return;
  }
  console.log('MySQL に接続成功!');
});

host にコンテナ名 mysql-server を指定すれば、Docker DNS が現在の IP に解決します。

ステップ 5:疎通確認

docker exec -it node-app sh

/ # ping mysql-server
PING mysql-server (172.20.0.2): 56 data bytes
64 bytes from 172.20.0.2: seq=0 ttl=64 time=0.089 ms
64 bytes from 172.20.0.2: seq=1 ttl=64 time=0.096 ms

コンテナ名の解決と ping が成功します。

DNS 解決の確認:

/ # nslookup mysql-server
Server:    127.0.0.11  # ← Docker 組み込み DNS
Address:   127.0.0.11:53

Name:      mysql-server
Address:   172.20.0.2  # ← MySQL の現在 IP

カスタムネットワークでは DNS サーバー(127.0.0.11)がコンテナ名を解決します。

MySQL を再起動して IP が変わっても、アプリは影響を受けません。DNS が解決を更新します。

トラブルシューティング

よく使う確認コマンド:

1. ネットワーク詳細

docker network inspect my-app-net

JSON で IP レンジ、ゲートウェイ、接続コンテナと各 IP が確認できます。

2. コンテナのネットワーク設定

docker inspect mysql-server | grep -A 20 Networks

接続ネットワークと各ネットワーク上の IP がわかります。

3. コンテナログ

docker logs node-app
docker logs mysql-server

接続エラーの詳細はログに出ることが多いです。

よくある問題と対処

問題想定原因対処
コンテナ名で ping 失敗同一ネットワークにいないdocker network inspect で確認、docker network connect で接続
ping は通るがアプリ接続失敗ポート設定ミスアプリのポートと MySQL のリスン(デフォルト 3306)を確認
DB が接続拒否認証情報・権限環境変数を確認、MySQL コンテナ内でユーザー権限を確認
DNS 解決エラーデフォルトネットワーク使用カスタムネットワークを作り、コンテナを再起動

応用のコツとベストプラクティス

マルチネットワーク:フロントとバックの分離

実プロジェクトでは、フロント・バックエンド・DB を別レイヤのネットワークに分けることもあります。

docker network create frontend-net
docker network create backend-net

docker run -d --name nginx \
  --network frontend-net \
  -p 80:80 \
  nginx:latest

docker run -d --name api-server \
  --network frontend-net \
  my-api:latest

docker network connect backend-net api-server

docker run -d --name postgres \
  --network backend-net \
  -e POSTGRES_PASSWORD=secret \
  postgres:14

効果:

  • nginx は api-server にアクセスできるが DB にはアクセスできない
  • api-server は DB にアクセスできる
  • DB はバックエンドからのみ到達可能でより安全

当社プロジェクトでもこの構成を使っています。

Docker Compose で管理を簡素化

コンテナが多いと手動管理は大変です。Docker Compose が有効です。

docker-compose.yml の例:

version: '3.8'

services:
  mysql:
    image: mysql:8.0
    container_name: mysql-server
    environment:
      MYSQL_ROOT_PASSWORD: my-secret-pw
      MYSQL_DATABASE: myapp_db
    networks:
      - app-network
    volumes:
      - mysql-data:/var/lib/mysql

  app:
    image: my-node-app:latest
    container_name: node-app
    ports:
      - "3000:3000"
    environment:
      DB_HOST: mysql  # ← service 名(container_name ではない)
      DB_USER: root
      DB_PASSWORD: my-secret-pw
      DB_NAME: myapp_db
    networks:
      - app-network
    depends_on:
      - mysql

networks:
  app-network:
    driver: bridge

volumes:
  mysql-data:

一発起動:

docker-compose up -d

Compose が自動で:

  • app-network を作成
  • 全コンテナをネットワークに接続
  • コンテナ間 DNS を設定
  • depends_on の順で起動(mysql → app)

停止・クリーンアップ:

docker-compose down
docker-compose down -v  # ボリュームも削除

個人的にはほぼ Compose 一択です。効率が段違いです。

その他のネットワークモード

bridge 以外にも用途別モードがあります。

ネットワークモード用途特徴
bridge単一ホスト上のマルチコンテナデフォルト。ブリッジ経由で隔離通信
host高性能ネットワークが必要ホストネットワークを直接使用。隔離なし、最速
overlayマルチホスト通信Swarm / Kubernetes 向け。複数マシン間の接続
none完全隔離ネットワーク IF なし。高セキュリティ用途

多くの場合は カスタム bridge で十分です。host は高頻度取引など極端な性能要求向け。overlay はオーケストレーション基盤の話で、通常は手動設定不要です。

よくある質問(FAQ)

Q1: IP では通るのにコンテナ名では通らないのはなぜ?

A: デフォルト bridge ネットワーク(docker0)にいるためです。DNS がなくコンテナ名解決に非対応。カスタムネットワークを作り、コンテナを参加させてください。

Q2: --link はまだ使える?

A: 今は動きますが非推奨で、将来削除の可能性があります。カスタムネットワークへ移行を。機能も強く、将来性があります。

Q3: カスタムネットワークは性能に影響する?

A: ほぼありません。デフォルトもカスタムも bridge で実装は同じ。DNS 分の差は無視できるレベルです。

Q4: コンテナはインターネットにアクセスできる?

A: 通常、bridge のコンテナは NAT で外部ネットワークに出られます。出られない場合は iptables やホスト側ネットワーク設定を確認してください。

Q5: 既存コンテナをカスタムネットワークへ移すには?

A:

docker network connect my-app-net old-container
docker network disconnect bridge old-container  # 任意

ただし --network で新規作成する方がおすすめです。

Q6: コンテナ名に大文字は使える?

A: 使えますが非推奨です。DNS 慣習では小文字・数字・ハイフンが無難です。

Q7: 1 コンテナが複数ネットワークにいられる?

A: はい。docker network connect で複数参加でき、複雑なトポロジが組めます。

まとめ

要点のおさらいです。

ステップ 1:問題の理解

  • デフォルトネットワークはコンテナ名解決不可、IP のみ
  • 再起動で IP が変わり接続が壊れる
  • --link は非推奨、使わない

ステップ 2:カスタムネットワーク作成

docker network create my-app-net

ステップ 3:ネットワーク参加とコンテナ名通信

docker run -d --name mysql-server --network my-app-net mysql:8.0

# アプリ側
host: 'mysql-server'  // IP ではなくコンテナ名

シンプルで Docker 公式推奨。コンテナ化アプリが安定し、保守も楽になります。

マイクロサービスやマルチコンテナプロジェクトなら:

  1. 今すぐ試す:既存プロジェクトをカスタムネットワーク化し、IP ハードコードをやめる
  2. Compose を試す:コンテナが 3 つ以上なら Compose 管理が楽
  3. 深掘りする:overlay と Kubernetes ネットワーク——クラウドネイティブの基礎

コンテナネットワークには学習曲線がありますが、一度掴むと Docker が格段に使いやすくなります。ターミナルを開き、最初のカスタムネットワークを作ってみてください。

コメント欄で質問があれば、できる範囲で返信します。

Docker コンテナ間通信の完全設定フロー

カスタムネットワークでコンテナ名解決の失敗と IP 変動を解決し、Web と DB を安定接続する

⏱️ 目安時間: 15 分

  1. 1

    ステップ1: 問題の根源を理解する:デフォルトネットワークの制限

    問題の根源:
    • Docker のデフォルトネットワーク(bridge)は IP アドレス通信のみで、コンテナ名解決に非対応
    • コンテナ再起動のたびに IP が再割り当てされ、アプリ設定の IP が無効になる

    デフォルトネットワークの制限:
    • 組み込み DNS がなく、IP でしかアクセスできない
    • コンテナ名の ping が失敗する(unknown host)
    • IP は変わるため本番向きではない

    実際のシーン:
    • MySQL コンテナは起動、Node.js アプリコンテナも動いている
    • しかしアプリはコンテナ名で DB に接続できず、IP のみ
    • 再起動で IP が変わり、設定が壊れる
  2. 2

    ステップ2: カスタムネットワークを作成する

    カスタムネットワークの作成:
    • docker network create でカスタムネットワークを作成
    • コマンド:docker network create my-app-net
    • コンテナ名解決に対応し、名前で相互アクセスできる
    • IP が変わってもアプリ設定はそのまま

    作成確認:
    • docker network ls で一覧確認
    • カスタムネットワークが作成されたことを確認
  3. 3

    ステップ3: 起動時にネットワークを指定する

    起動時のネットワーク指定:
    • --network パラメータでネットワークを指定
    • コマンド:docker run -d --name mysql-server --network my-app-net mysql:8.0
    • アプリでは host: 'mysql-server'(IP ではなくコンテナ名)

    接続確認:
    • docker exec -it web-container ping mysql-server で ping
    • またはアプリから DB 接続をテスト
  4. 4

    ステップ4: docker-compose でネットワークを自動作成する

    応用:docker-compose でネットワークを自動作成

    docker-compose.yml でネットワーク定義:
    • networks:
    my-app-net:
    driver: bridge
    • サービスは同一ネットワークに参加し、コンテナ名が自動解決。設定がシンプルで信頼性が高い

    docker-compose の例:
    • services でサービス定義
    • networks でネットワーク定義
    • 指定ネットワークに自動参加、コンテナ名解決

    シンプルかつ Docker 公式推奨。コンテナ化アプリが安定し、保守も楽になる。

FAQ

なぜコンテナ名で ping できない?デフォルトネットワークの制限は?
問題の根源:Docker のデフォルトネットワーク(bridge)は IP アドレス通信のみでコンテナ名解決に非対応。コンテナ再起動のたびに IP が再割り当てされ、アプリ設定の IP が無効になります。

デフォルトネットワークの制限:
• 組み込み DNS がない
• IP でしかアクセスできない
• コンテナ名の ping が失敗(unknown host)
• IP は変わるため本番向きではない

実際のシーン:MySQL は起動、Node.js も動いているが、コンテナ名では DB に接続できず IP のみ。再起動で IP が変わり設定が壊れる。
コンテナ間通信の問題はどう解決する?カスタムネットワークの設定は?
解決策:カスタムネットワークを使う。コンテナ名解決に対応し、名前で相互アクセスできる。IP が変わってもアプリ設定はそのまま。Docker 公式推奨のベストプラクティス。

実践の流れ:
1. カスタムネットワーク作成:docker network create my-app-net
2. 起動時にネットワーク指定:docker run --network my-app-net
3. アプリでコンテナ名を host に:host: 'mysql-server'
4. 接続確認:コンテナ名で ping またはアプリ接続テスト
docker-compose でコンテナネットワークをどう設定する?
応用:docker-compose でネットワークを自動作成。

設定手順:
• docker-compose.yml で networks を定義(networks: my-app-net: driver: bridge)
• サービスは同一ネットワークに自動参加
• コンテナ名が自動解決
• 設定がシンプルで信頼性が高い

docker-compose の例:
• services でサービス定義
• networks でネットワーク定義
• 指定ネットワークに自動参加
• コンテナ名解決

シンプルかつ Docker 公式推奨。コンテナ化アプリが安定し、保守も楽になる。

4分で読めます · 公開日: 2025年12月17日 · 更新日: 2026年6月8日

関連記事

コメント

GitHubアカウントでログインしてコメントできます