Docker networkで接続できない原因と解決方法|初心者向け完全ガイド

Docker

Docker networkで接続できない原因と解決方法|初心者向け完全ガイド

Dockerを使用してマイクロサービスアーキテクチャを構築する際、複数のコンテナ間の通信は非常に重要です。しかし、Docker networkで接続できないトラブルに直面することは多くの開発者が経験します。本記事では、Docker networkの接続問題の原因と具体的な解決方法について、初心者でもわかりやすく解説します。

Docker networkで接続できない主な原因

Docker networkで接続できない場合、以下のような原因が考えられます。

1. ネットワークが存在しない、または異なるネットワークに接続している

最も一般的な原因は、複数のコンテナが同じネットワークに接続していないことです。Dockerでは、同じネットワーク上にあるコンテナ同士のみが通信できます。異なるネットワークに接続しているコンテナ間では通信ができません。

2. ファイアウォールまたはセキュリティグループの設定

Dockerコンテナ内またはホストマシンのファイアウォール設定が通信をブロックしている場合があります。特にポート指定が不適切な場合、接続が失敗します。

3. DNSの名前解決が失敗している

Dockerネットワークは内部DNSサーバーを提供していますが、このDNSが正しく機能していない場合、コンテナ名による名前解決に失敗します。

4. ポート番号の誤設定

コンテナが特定のポートでリッスンしていない、または正しくマッピングされていない場合、接続できません。

5. コンテナが正常に起動していない

接続先のコンテナがクラッシュしているか、正常に起動していない場合、当然接続できません。

Docker network接続問題の解決手順

ステップ1: 既存のネットワークを確認する

まず、現在利用可能なDockerネットワークを確認しましょう。

docker network ls

このコマンドで、bridgeネットワーク、hostネットワーク、overlayネットワークなどが表示されます。デフォルトではbridgeというネットワークが作成されています。

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

本番環境では、デフォルトのbridgeネットワークよりもカスタムネットワークの使用が推奨されます。以下のコマンドでカスタムネットワークを作成します。

docker network create my-network

このコマンドで「my-network」という名前のbridgeネットワークが作成されます。

ステップ3: コンテナをネットワークに接続する

コンテナを起動する際に、–networkオプションを使用してネットワークを指定します。

docker run -d --name web-app --network my-network -p 8080:3000 my-web-image
docker run -d --name database --network my-network my-db-image

ステップ4: コンテナ間の接続を確認する

接続が正常に機能しているか確認するには、以下のコマンドを使用します。

docker network inspect my-network

このコマンドで、ネットワークに接続しているコンテナが表示されます。

ステップ5: ping/nslookupで名前解決を確認する

コンテナ内から別のコンテナへの接続をテストします。

docker exec web-app ping database

これにより、databaseコンテナが到達可能かどうかを確認できます。

実践的なコード例

例1: 複数コンテナのDocker Compose設定

Docker Composeを使用することで、複数のコンテナの管理がより簡単になります。以下は、WebアプリケーションとPostgreSQLデータベースを接続する例です。

version: '3.8'

services:
  web:
    image: nginx:latest
    container_name: web-server
    ports:
      - \"8080:80\"
    networks:
      - app-network
    environment:
      - DB_HOST=database
      - DB_PORT=5432
    depends_on:
      - database

  database:
    image: postgres:13
    container_name: postgres-db
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: password123
      POSTGRES_DB: mydb
    networks:
      - app-network
    volumes:
      - db-data:/var/lib/postgresql/data
    expose:
      - \"5432\"

networks:
  app-network:
    driver: bridge

volumes:
  db-data:

このdocker-compose.ymlファイルで重要なポイントは、両サービスが同じ「app-network」に接続していることです。これにより、webコンテナからdatabaseコンテナへ「database:5432」でアクセス可能になります。

例2: Node.jsアプリケーションからの接続

Node.jsアプリケーションがPostgreSQLデータベースに接続する場合のコード例です。

const { Client } = require('pg');

const client = new Client({
  user: process.env.DB_USER || 'admin',
  password: process.env.DB_PASSWORD || 'password123',
  host: process.env.DB_HOST || 'database', // コンテナ名で指定
  port: process.env.DB_PORT || 5432,
  database: process.env.DB_NAME || 'mydb'
});

client.connect((err) => {
  if (err) {
    console.error('接続エラー:', err.stack);
  } else {
    console.log('データベースに接続しました');
  }
});

module.exports = client;

重要なのは、hostnameをコンテナ名である「database」で指定していることです。Docker Composeのカスタムネットワークでは、サービス名が自動的にDNS名として解決されます。

例3: 手動でコンテナを実行して接続する場合

# カスタムネットワークを作成
docker network create app-network

# PostgreSQLコンテナを起動
docker run -d \\
  --name postgres-db \\
  --network app-network \\
  -e POSTGRES_PASSWORD=password123 \\
  postgres:13

# Node.jsアプリケーションコンテナを起動
docker run -d \\
  --name node-app \\
  --network app-network \\
  -p 3000:3000 \\
  -e DB_HOST=postgres-db \\
  -e DB_PASSWORD=password123 \\
  my-node-app:latest

# 接続テスト
docker exec node-app curl http://postgres-db:5432

例4: Pythonアプリケーションからの接続確認

import psycopg2
import os

try:
    connection = psycopg2.connect(
        host=os.getenv('DB_HOST', 'database'),
        port=os.getenv('DB_PORT', '5432'),
        user=os.getenv('DB_USER', 'admin'),
        password=os.getenv('DB_PASSWORD', 'password123'),
        database=os.getenv('DB_NAME', 'mydb')
    )
    
    cursor = connection.cursor()
    cursor.execute('SELECT version();')
    version = cursor.fetchone()
    print(f\"PostgreSQLバージョン: {version}\")
    
    cursor.close()
    connection.close()
    print(\"接続テスト成功\")
    
except (Exception, psycopg2.Error) as error:
    print(f\"接続エラー: {error}\")

Docker network接続で良くある間違い

間違い1: デフォルトのbridgeネットワークを使用している

多くの初心者がデフォルトのbridgeネットワークを使用していますが、これは推奨されません。理由は、デフォルトbridgeネットワークではコンテナ名によるDNS解決がサポートされていないためです。

# 間違い:デフォルトネットワークを使用
docker run -d --name web nginx
docker run -d --name db postgres

# 正しい:カスタムネットワークを使用
docker network create app-net
docker run -d --name web --network app-net nginx
docker run -d --name db --network app-net postgres

間違い2: ポートマッピングとexposeの混同

-pオプションはホストマシンへのポート公開、exposeはコンテナ間通信用です。正しく使い分けることが重要です。

#間違い:exposedだけではホストからアクセスできない
docker run -d --name web --expose 8080 nginx

# 正しい:ホストからアクセス可能
docker run -d --name web -p 8080:80 nginx

# 正しい:コンテナ間通信のみ
docker run -d --name db --expose 5432 postgres

間違い3: 環境変数の忘れ

コンテナ間通信する場合、接続先のホスト名や認証情報を環境変数で正しく設定する必要があります。

# 間違い:ホスト名がハードコードされている
docker run -d --name app my-app  # アプリ内でlocalhostを参照

# 正しい:環境変数で動的に設定
docker run -d --name app \\
  -e DB_HOST=database \\
  -e DB_PORT=5432 \\
  my-app

間違い4: ネットワーク指定なしでコンテナを起動

–networkオプションを指定せずにコンテナを起動すると、デフォルトのbridgeネットワークに接続されます。

# 間違い
docker run -d --name web nginx

# 正しい
docker run -d --name web --network app-network nginx

間違い5: コンテナが起動していないのに接続をテスト

接続テストを行う前に、対象のコンテナが正常に起動していることを確認する必要があります。

# コンテナの状態確認
docker ps -a

# ログを確認
docker logs database

# 起動していない場合は起動
docker start database

トラブルシューティングのチェックリスト

Docker network接続がうまくいかない場合、以下のチェックリストを確認してください:

  • □ 両方のコンテナが同じネットワークに接続しているか確認(docker network inspect)
  • □ コンテナが正常に起動しているか確認(docker ps)
  • □ コンテナ内のアプリケーションが正しくポートをリッスンしているか確認(docker exec … netstat -tlnp)
  • □ ファイアウォールがコンテナ間通信をブロックしていないか確認
  • □ 環境変数が正しく設定されているか確認(docker inspect)
  • □ アプリケーション内でコンテナ名またはサービス名をホスト名として使用しているか確認
  • □ ログファイルを確認してエラーメッセージがないか確認(docker logs)

まとめ

Docker networkで接続できない問題は、基本を理解すれば解決できます。重要なポイントをまとめます:

  1. カスタムネットワークを使用する: デフォルトのbridgeではなく、docker network createで作成したカスタムネットワークを使用してください。
  2. 同じネットワークに接続する: 通信するすべてのコンテナが同じネットワークに接続していることを確認してください。
  3. コンテナ名で参照する: カスタムネットワーク上では、IPアドレスではなくコンテナ名またはサービス名で通信相手を指定できます。
  4. 環境変数を活用する: ハードコードを避け、環境変数でホスト名やポートを指定しましょう。
  5. Docker Composeを使用する: 複数のコンテナを管理する場合は、docker-compose.ymlでネットワークを一括管理すると便利です。
  6. ログを確認する: トラブル発生時は、docker logsコマンドで詳細なエラーメッセージを確認してください。

これらの原則に従うことで、Docker network接続の問題のほとんどは解決できます。開発環境から本番環境への移行を検討する際も、同じ考え方が適用されるため、早めに正しい方法を習慣づけることが重要です。

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