更新: 2026年03月 · 9 分で読める · 4,736 文字
Docker Composeで複数サービスを統合する実践的な書き方
本記事では、Docker Composeの設定ファイル(docker-compose.yml)を正しく書くための実践的なテクニックを解説します。マイクロサービス環境でWebアプリ・データベース・キャッシュを同時に立ち上げる具体例を通じて、すぐに仕事で活用できるパターンを習得できます。
Docker Composeの基本構造を理解する
Docker Composeは複数のコンテナを一度に定義・実行するツールです。YAML形式の設定ファイル(docker-compose.yml)に記述します。単一のコンテナで事足りる場合はDocker CLIで十分ですが、複数サービスの依存関係やネットワーク設定が必要な場面でDocker Composeが活躍します。
使うべき場面: 開発環境・テスト環境構築、ローカルでのマイクロサービス検証
使うべきでない場面: 本番環境での大規模オーケストレーション(Kubernetesを検討)、単一コンテナの運用
YAMLファイルの基本スキーマ
docker-compose.ymlは以下の構造が基本になります。
version: '3.8'
services:
# サービス定義
web:
image: nginx:latest
ports:
- "8080:80"
depends_on:
- db
db:
image: postgres:15
environment:
POSTGRES_PASSWORD: password123
volumes:
# 名前付きボリューム定義
db_data:
networks:
# ネットワーク定義
default:
driver: bridge
実践的なマルチサービス構成の書き方
Webアプリ + PostgreSQL + Redisの統合例
開発現場でよく使う3層構成を実装してみます。このパターンをマスターすれば、ほとんどのDocker Compose案件に対応できます。
version: '3.8'
services:
# Node.jsのWebアプリケーション
api:
build:
context: .
dockerfile: Dockerfile
container_name: app_api
ports:
- "3000:3000"
environment:
DATABASE_URL: postgresql://user:password@postgres:5432/myapp
REDIS_URL: redis://redis:6379
NODE_ENV: development
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_started
volumes:
- .:/app
- /app/node_modules
networks:
- backend
restart: unless-stopped
# PostgreSQLデータベース
postgres:
image: postgres:15-alpine
container_name: app_postgres
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: myapp
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 10s
timeout: 5s
retries: 5
networks:
- backend
restart: unless-stopped
# Redisキャッシュ
redis:
image: redis:7-alpine
container_name: app_redis
ports:
- "6379:6379"
volumes:
- redis_data:/data
networks:
- backend
restart: unless-stopped
volumes:
postgres_data:
redis_data:
networks:
backend:
driver: bridge
重要な設定項目の解説
build vs image: buildを使用するとDockerfileをビルドし、imageを使用するとレジストリから直接プルします。開発中はbuildで柔軟に対応し、本番ではimageで安定性を重視します。
depends_on: サービス起動順序を制御します。conditionパラメータで起動完了の判定方法を指定できます。service_healthyを使う場合、対象サービスにhealthcheckの設定が必須です。
healthcheck: サービスの健全性をチェックします。PostgreSQLの場合、pg_isreadyコマンドでの確認が標準的です。起動時間が長いサービスでは重要な役割を果たします。
volumes: コンテナ内ディレクトリをホストマシンやボリュームにマウントします。ホストパス:コンテナパスで指定します。開発時にソースコードをマウントすることでホットリロードが可能になります。
よくあるハマりポイントと解決策
サービス間通信が失敗する場合
問題: APIコンテナからlocalhostでPostgresに接続しようとするとエラーが出る。
原因: コンテナ内のlocalhostはコンテナ自身を指しており、別のコンテナには到達しません。
解決策: サービス名でホスト名を指定します。docker-composeは自動的にサービス名をDNS名として解決します。上記の例では、APIコンテナからpostgresql://user:password@postgres:5432/myappでPostgresに接続できます。
ボリュームがマウントされない
問題: ホストマシンの変更がコンテナに反映されない。
原因: 相対パスの解釈、パーミッション問題、またはコンテナが古いイメージで起動している。
解決策: 以下を確認します。
# 既存のコンテナ・イメージを全削除して再構築
docker-compose down -v
docker-compose up --build
# ボリュームマウント状況を確認
docker inspect コンテナ名 | grep Mounts
起動順序の問題でDBにアクセスできない
問題: APIが起動してもPostgresがまだ完全に初期化されていない。
原因: depends_onでservice_startedを指定すると、プロセスが起動しただけの状態で依存サービスが起動してしまう。
解決策: healthcheckを設定し、depends_onのconditionをservice_healthyに指定します。上記の例がこの実装パターンです。
本番環境に向けた設定のコツ
環境変数の外部管理
パスワードやAPIキーをdocker-compose.ymlに直書きしてはいけません。.envファイルで管理します。
# .env ファイル
POSTGRES_USER=produser
POSTGRES_PASSWORD=SecurePass123!
DATABASE_URL=postgresql://produser:SecurePass123!@postgres:5432/myapp
NODE_ENV=production
# docker-compose.yml内で参照
environment:
DATABASE_URL: ${DATABASE_URL}
NODE_ENV: ${NODE_ENV}
Gitに.envをコミットしないよう.gitignoreに追加してください。
ネットワーク分離
複数のプロジェクトを同時に実行する場合、ネットワーク分離が重要です。
networks:
backend:
driver: bridge
name: myapp_backend
frontend:
driver: bridge
name: myapp_frontend
明示的にネットワーク名を指定することで、名前衝突を回避できます。
Docker Composeとの比較・代替ツール
Podman Compose: Dockerの代替ランタイムであるPodmanのCompose互換ツール。Dockerless環境で利用できますが、互換性が100%ではありません。
Kubernetes(kubectl): 本番環境での標準的なオーケストレーションツール。複雑なデプロイメント、スケーリング、ローリングアップデートが必要な場合に選択します。
実際の動作確認方法
以下のコマンドで動作確認できます(テスト環境: macOS 14 / Docker 25.0 / docker-compose 2.24)。
# コンテナの起動
docker-compose up -d
# ログの確認
docker-compose logs -f api
# 特定サービスへのアクセス確認
docker-compose exec api curl http://postgres:5432
# コンテナの停止
docker-compose down
# ボリュームまで削除
docker-compose down -v
よくある質問
A: 最新の3.8を推奨します。Docker Compose v2では1と2のバージョン値に意味がなくなりましたが、互換性のため3.xを記述するのが慣例です。古いDocker環境では2.1や3.0も選択肢ですが、新規プロジェクトは3.8以上を使用してください。
A: はい、docker-compose.ymlで可能です。serviceセクション内にcommandやentrypointキーを追加すると、イメージに含まれる設定を上書きできます。例えば開発環境でノーダイスターターツール(nodemon)を使う場合、command: npm run dev のように指定します。
A: ports設定でコンテナ側のみ指定すれば、ホスト側は自動割り当てされます。例えば ports: - "8080" とするとランダムなポートがホストに割り当てられます。実際の割り当て結果は docker-compose ps で確認できます。
まとめ
- docker-compose.ymlはversion、services、volumes、networksの4要素で構成される
- depends_onとhealthcheckを組み合わせることで確実な起動順序制御ができる
- サービス名がDNS名として自動解決されるため、ホスト名として直接指定可能
- 環境変数は.envファイルで外部管理し、パスワードなどの機密情報は直書きしない
- development環境ではbuildでイメージを構築、production環境ではimageで明示的なバージョンを指定
- 複雑な本番構成ではKubernetesへの移行を検討する
Docker Composeを適切に設定することで、チーム全体で同じ開発環境を再現できます。本記事のテンプレートを活用し、プロジェクトに合わせてカスタマイズしてみてください。
おすすめDevOpsリソース
- Docker Documentation Official Docker and Docker Compose reference.
- Kubernetes Docs Official K8s documentation. Great for understanding concepts.
- GitHub Actions Docs Official guide for CI/CD workflows.