Docker Composeのネットワーク接続エラーを完全解決!設定方法とトラブルシューティング
はじめに
Docker Composeを使ってマルチコンテナアプリケーションを構築している際、コンテナ間の通信がうまくいかないというエラーに遭遇した経験はありませんか?このネットワーク関連のエラーは、初心者から経験者まで多くの開発者が経験する一般的な問題です。本記事では、Docker Composeのネットワーク接続エラーの原因から解決方法まで、わかりやすく解説します。
Docker Composeネットワークエラーの原因
1. デフォルトネットワークの理解不足
Docker Composeを起動すると、自動的にプロジェクト用の独立したネットワークが作成されます。このネットワーク内でのみ、コンテナ間の通信が可能になります。外部のネットワークやホストマシンとの通信が必要な場合は、明示的な設定が必要です。
2. サービス名によるホスト名解決の失敗
Docker Composeでは、docker-compose.ymlに定義したサービス名が、コンテナ内でのホスト名として機能します。しかし、このホスト名解決が失敗する場合があります。主な原因は以下の通りです:
- ネットワークが正しく設定されていない
- サービス名のタイプミス
- コンテナがまだ起動していない状態でのアクセス試行
- 異なるネットワークのコンテナ間での通信試行
3. ポートマッピングとポート公開の混同
ports設定とexpose設定の違いを理解していないことが原因になります。portsはホストマシンへのポート公開、exposeはコンテナ内ネットワークへのポート公開です。
4. ネットワークドライバーの非互換性
Docker Composeで指定できるネットワークドライバー(bridge、overlay等)が、目的に合致していない場合も考えられます。
Docker Composeネットワークの基本概念
デフォルトネットワーク動作
Docker Composeを実行すると、以下のプロセスが自動的に行われます:
- プロジェクト用のブリッジネットワークが自動作成される
- 各サービスがこのネットワークに接続される
- DNS サーバーが起動し、サービス名解決が有効になる
- 同じネットワーク内のコンテナは、サービス名でお互いに通信可能
ホスト名解決のメカニズム
Docker Composeネットワーク内では、各コンテナは以下のホスト名で参照可能です:
- サービス名(例:db、web)
- コンテナ名(例:myproject_db_1)
- サービス名.ネットワーク名
解決手順
ステップ1:docker-compose.ymlの基本設定を確認
まず、docker-compose.ymlファイルが正しく構成されているか確認しましょう。バージョンとサービス定義が必須です。
version: '3.8'
services:
web:
image: nginx:latest
ports:
- "80:80"
networks:
- app-network
db:
image: postgres:13
environment:
POSTGRES_PASSWORD: example
networks:
- app-network
networks:
app-network:
driver: bridge
ステップ2:ネットワーク設定を明示的に定義
ネットワークセクションで明示的にネットワークを定義することで、コンテナ間通信がより安定します。
version: '3.8'
services:
api:
build: ./api
container_name: api_container
ports:
- "3000:3000"
networks:
- backend
depends_on:
- database
database:
image: mysql:8.0
container_name: db_container
environment:
MYSQL_ROOT_PASSWORD: root_pass
MYSQL_DATABASE: mydb
networks:
- backend
volumes:
- db_data:/var/lib/mysql
networks:
backend:
driver: bridge
volumes:
db_data:
ステップ3:depends_onで起動順序を制御
コンテナの起動順序を指定することで、接続エラーを防げます。
version: '3.8'
services:
web:
image: nginx:latest
depends_on:
- app
networks:
- app-network
app:
build: .
depends_on:
- redis
networks:
- app-network
redis:
image: redis:7
networks:
- app-network
networks:
app-network:
driver: bridge
ステップ4:接続確認とデバッグ
コンテナ内から実際に接続可能かテストします。
# コンテナ内でシェルを実行
docker-compose exec web bash
# サービス名でpingテスト
ping db
# DNS解決を確認
nslookup db
# ポート接続を確認
nc -zv db 5432
実践的なコード例
例1:Node.js + PostgreSQL の構成
version: '3.8'
services:
nodejs_app:
build:
context: .
dockerfile: Dockerfile
container_name: nodejs_app
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://user:password@postgres:5432/mydb
- NODE_ENV=development
depends_on:
- postgres
networks:
- app-network
volumes:
- ./src:/app/src
postgres:
image: postgres:14-alpine
container_name: postgres_db
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: mydb
networks:
- app-network
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 10s
timeout: 5s
retries: 5
networks:
app-network:
driver: bridge
volumes:
postgres_data:
Node.jsアプリケーションからの接続例:
// connection.js
const { Pool } = require('pg');
const pool = new Pool({
user: 'user',
password: 'password',
host: 'postgres', // サービス名を使用
port: 5432,
database: 'mydb'
});
pool.query('SELECT NOW()', (err, result) => {
if (err) {
console.error('Connection error:', err);
} else {
console.log('Connected:', result.rows);
}
});
例2:複数ネットワークの構成
version: '3.8'
services:
web:
image: nginx:latest
networks:
- frontend
ports:
- "80:80"
api:
build: ./api
networks:
- frontend
- backend
depends_on:
- database
database:
image: postgres:13
networks:
- backend
environment:
POSTGRES_PASSWORD: secret
networks:
frontend:
driver: bridge
backend:
driver: bridge
例3:環境変数を使用した柔軟な設定
version: '3.8'
services:
web:
build: ./web
ports:
- "${WEB_PORT}:3000"
environment:
- DB_HOST=${DB_HOST:-database}
- DB_PORT=${DB_PORT:-5432}
- DB_NAME=${DB_NAME:-mydb}
networks:
- app-network
depends_on:
- database
database:
image: postgres:${POSTGRES_VERSION:-13}
environment:
POSTGRES_DB: ${DB_NAME:-mydb}
POSTGRES_PASSWORD: ${DB_PASSWORD:-password}
networks:
- app-network
volumes:
- db_data:/var/lib/postgresql/data
networks:
app-network:
driver: bridge
volumes:
db_data:
.envファイル:
WEB_PORT=8080
DB_HOST=database
DB_PORT=5432
DB_NAME=production_db
DB_PASSWORD=secure_password
POSTGRES_VERSION=14
よくある間違いと対処法
間違い1:localhost でのアクセス試行
❌ 間違ったコード:
const connection = mysql.createConnection({
host: 'localhost', // これは間違い
user: 'root',
password: 'password',
database: 'mydb'
});
✅ 正しいコード:
const connection = mysql.createConnection({
host: 'database', // docker-compose.ymlで定義したサービス名
user: 'root',
password: 'password',
database: 'mydb'
});
間違い2:ネットワーク設定の省略
❌ 間違ったコード:
version: '3.8'
services:
web:
image: nginx:latest
db:
image: postgres:13
# ネットワーク設定がない場合、通信が不安定になる可能性がある
✅ 正しいコード:
version: '3.8'
services:
web:
image: nginx:latest
networks:
- app-network
db:
image: postgres:13
networks:
- app-network
networks:
app-network:
driver: bridge
間違い3:ポート設定の混同
❌ 間違ったコード:
services:
api:
build: .
ports:
- "3000:3000"
# ポート3000はホストに公開されるが、
# コンテナから別のコンテナへアクセスする際は
# ホストのポートではなく、コンテナのポート3000を使用
✅ 正しい理解:
services:
api:
build: .
expose:
- "3000" # コンテナネットワーク内で公開
ports:
- "3000:3000" # ホストマシンにも公開
consumer:
build: ./consumer
# api コンテナにアクセスする際
# http://api:3000 を使用(expose/ports に関わらず)
間違い4:起動順序の制御なし
❌ 間違ったコード:
version: '3.8'
services:
app:
build: .
# depends_on がないため、db より先に起動しようとする可能性がある
db:
image: postgres:13
✅ 正しいコード:
version: '3.8'
services:
app:
build: .
depends_on:
db:
condition: service_healthy
db:
image: postgres:13
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
トラブルシューティング コマンド集
ネットワーク接続エラーをデバッグする際に役立つコマンド:
# 1. ネットワーク一覧を表示
docker network ls
# 2. 特定のネットワーク詳細を表示
docker network inspect project_app-network
# 3. コンテナ間接続テスト
docker-compose exec web curl http://api:3000
# 4. DNS解決をテスト
docker-compose exec web getent hosts db
# 5. ネットワークインターフェース確認
docker-compose exec web ip addr
# 6. ポート開放状況の確認
docker-compose exec api netstat -tlnp
# 7. コンテナログの確認
docker-compose logs api
# 8. 特定サービスのみログ表示
docker-compose logs -f api
# 9. コンテナを再起動
docker-compose restart api
# 10. ネットワークを再作成(完全なクリーンアップ)
docker-compose down
docker-compose up -d
ベストプラクティス
1. 明示的なネットワーク定義
常にnetworksセクションを明示的に定義し、サービスをそのネットワークに接続しましょう。
2. ヘルスチェックの実装
データベースなどのサービスにはhealthcheckを設定し、完全な起動を待つようにします。
3. 環境変数の活用
.envファイルを使用して、設定を柔軟に管理します。
4. 接続リトライロジック
アプリケーション側でも、サービスへの接続にリトライロジックを実装します。
// リトライロジックの実装例
async function connectWithRetry(config, maxRetries = 5) {
for (let i = 0; i < maxRetries; i++) {
try {
const connection = await createConnection(config);
console.log('Connected successfully');
return connection;
} catch (error) {
console.log(`Attempt ${i + 1} failed, retrying...`);
if (i === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, 2000));
}
}
}
5. 本番環境への適用
ローカル開発での成功をそのまま本番環境に適用せず、セキュリティとスケーラビリティを考慮した設定に変更します。
まとめ
Docker Composeのネットワーク接続エラーは、適切な設定と理解があれば十分に解決できる問題です。本記事で解説した以下のポイントを押さえることが重要です:
- 自動ネットワーク作成の理解:Docker Composeはプロジェクト用のブリッジネットワークを自動作成し、サービス名でのホスト名解決を提供します
- 明示的な設定:ネットワークを明示的に定義することで、より安定した構成が実現できます
- localhost ではなくサービス名:コンテナ間通信ではlocalhost ではなく、docker-compose.yml で定義したサービス名を使用します
- 起動順序の制御:depends_on とhealthcheck で起動順序と準備完了状態を管理します
- デバッグ手法:docker-compose logs や exec コマンドで、問題を効率的に診断できます
これらのベストプラクティスを実装することで、Docker Compose を使ったマルチコンテナアプリケーション開発がより安定し、生産性が向上します。問題が発生した場合は、提供したトラブルシューティングコマンドを活用し、段階的に問題を解決していくことをお勧めします。
Docker Compose のネットワーク機能を完全に理解することで、スケーラブルで保守性の高いコンテナアプリケーションを構築できるようになるでしょう。

