Docker: Compose の高度なオーケストレーション
最終更新:2026-08-26
開発、テスト、本番——1 つの Compose ファイルで 3 つの環境をすべて扱えます。
1. 学べること
- プロファイル: 複数環境の設定
- 設定の再利用と継承(extends / override)
- 水平スケーリング
- リソース制限の指針
- ヘルスチェックによる依存制御
2. テックリードの実話
(1) 悩み: 3 つの環境、3 つの設定ファイル
Charlie は開発・テスト・本番の 3 環境のために別々の Compose 設定を維持しなければなりません。開発環境ではホットリロードとデバッグツールが必要、テスト環境では完全なサービススタックが必要、本番環境ではリソース制限と複数レプリカが必要です。3 つの別々の YAML ファイルには重複するコードが多く、どこか 1 つを変更するには 3 つのファイルをすべて修正しなければなりません。
(2) プロファイル + override による解決
Charlie は「1 つの基本設定 + 環境別オーバーライド」という構成を、プロファイルとオーバーライドファイルで実現しました。
BASH
# 開発: dev プロファイル + dev オーバーライドを有効化
docker compose --profile dev -f docker-compose.yml -f docker-compose.dev.yml up -d
# 本番: prod オーバーライドのみ
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
(3) 成果: 3 ファイル → 1 + 2 ファイル
完全に独立した 3 つのファイルから、1 つの基本ファイル + 2 つの差分オーバーライドファイルへ。共通設定を 1 か所でだけ管理すればよくなりました。
3. プロファイル: 複数環境の設定
(1) プロファイルの仕組み
graph TB
BASE["docker-compose.yml<br/>基本サービス"] --> DEV["--profile dev<br/>+ dev ツール(ホットリロード、adminer)"]
BASE --> TEST["--profile test<br/>+ テストランナー(selenium)"]
BASE --> PROD["--profile prod<br/>+ 監視(prometheus、grafana)"]
▶ サンプル: --profile dev を有効化 (難易度: ⭐⭐)
YAML
# プロファイル付き docker-compose.yml
services:
api:
build: .
ports:
- "5000:5000"
environment:
- FLASK_ENV=development
db:
image: postgres:15-alpine
volumes:
- pg-data:/var/lib/postgresql/data
# dev 専用: データベース管理 UI
adminer:
image: adminer
ports:
- "8081:8080"
profiles: ["dev"]
depends_on: [db]
# dev 専用: flask debug によるホットリロード
api-dev:
build:
context: .
dockerfile: Dockerfile.dev
volumes:
- ./src:/app
ports:
- "5000:5000"
- "5678:5678" # デバッグポート
environment:
- FLASK_DEBUG=1
profiles: ["dev"]
# prod 専用: Prometheus 監視
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
profiles: ["prod"]
volumes:
pg-data:
BASH
# 開発: 基本サービス + dev プロファイル
docker compose --profile dev up -d
# 本番: 基本サービス + prod プロファイル
docker compose --profile prod up -d
# 基本サービスのみ(プロファイルなし)
docker compose up -d
(2) プロファイルと override の比較
| 比較項目 | プロファイル | override ファイル |
|---|---|---|
| ファイル数 | 1 ファイル | 2〜3 ファイル |
| 有効化方法 | --profile xxx |
-f base.yml -f override.yml |
| 向いている場面 | サービスの増減 | 設定の差分が大きい |
| 組み合わせ | 複数プロファイルを同時有効可 | 順番にマージ |
4. override ファイルのマージ
▶ サンプル: override ファイルによる設定の上書き (難易度: ⭐⭐⭐)
YAML
# docker-compose.yml(基本設定)
services:
api:
build: .
environment:
FLASK_ENV: production
restart: unless-stopped
db:
image: postgres:15-alpine
volumes:
- pg-data:/var/lib/postgresql/data
restart: unless-stopped
volumes:
pg-data:
YAML
# docker-compose.dev.yml(dev 用オーバーライド)
services:
api:
environment:
FLASK_ENV: development
FLASK_DEBUG: "1"
volumes:
- ./src:/app # ホットリロード: ソースコードをマウント
ports:
- "5678:5678" # デバッグポート
# dev 専用サービス
adminer:
image: adminer
ports:
- "8081:8080"
YAML
# docker-compose.prod.yml(prod 用オーバーライド)
services:
api:
deploy:
replicas: 3
resources:
limits:
cpus: "1.0"
memory: 512M
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
interval: 30s
timeout: 5s
retries: 3
# prod 専用: Nginx リバースプロキシ
nginx:
image: nginx:1.25-alpine
ports:
- "80:80"
volumes:
- ./nginx.prod.conf:/etc/nginx/conf.d/default.conf
depends_on:
- api
BASH
# 開発
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d
# 本番
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# マージ後の設定をプレビュー(ドライラン)
docker compose -f docker-compose.yml -f docker-compose.prod.yml config
5. 水平スケーリング
▶ サンプル: --scale でレプリカ数を指定 (難易度 ⭐⭐)
BASH
# API サービスを 3 レプリカにスケール
docker compose up -d --scale api=3
# 動作中のスタックを動的にスケール
docker compose up -d --scale api=5
(1) スケーリング時の注意点
| 問題 | 原因 | 解決策 |
|---|---|---|
| ポート競合 | 複数レプリカが同じホストポートにマッピング | エントリーポイント(Nginx)のみ公開し、API はホストポートにマップしない |
| データ整合性 | 同じストレージへの複数書き込み | ステートレスなサービスのみスケール対象にする、データベースを共有 |
| 負荷分散 | 複数レプリカへリクエストをどう分散するか | Nginx upstream または Docker の組み込み DNS ラウンドロビン |
▶ サンプル: デプロイ.replicas で宣言的にスケール (難易度: ⭐⭐)
YAML
services:
api:
build: .
deploy:
replicas: 3
resources:
limits:
cpus: "0.5"
memory: 256M
reservations:
cpus: "0.25"
memory: 128M
# スケール対象サービスにはポートをマップしない
# ports: ["5000:5000"] ← replicas > 1 の場合競合する
nginx:
image: nginx:alpine
ports:
- "80:80"
# Nginx upstream が api:5000 へ DNS ラウンドロビンで分散
6. リソース制限
(1) デプロイ.resources の設定
YAML
services:
api:
deploy:
resources:
limits: # ハードリミット(超過時は強制終了)
cpus: "1.0"
memory: 512M
reservations: # ソフト保証(最小割り当て)
cpus: "0.5"
memory: 256M
| フィールド | 用途 | 超過時の挙動 |
|---|---|---|
limits.cpus |
CPU 上限 | 超過時、スロットリング |
limits.memory |
メモリ上限 | 超過時、OOM Kill |
reservations.cpus |
最小 CPU 保証 | スケジューリング保証 |
reservations.memory |
最小メモリ保証 | スケジューリング保証 |
7. 完全なサンプル: 3 環境向け Compose プロジェクト
YAML
# ============================================
# docker-compose.yml - 基本設定
# ============================================
services:
api:
build:
context: .
dockerfile: Dockerfile
environment:
DATABASE_URL: postgresql://postgres:${DB_PASSWORD:-secret}@db:5432/${DB_NAME:-myapp}
depends_on:
db:
condition: service_healthy
restart: unless-stopped
networks:
- backend
db:
image: postgres:15-alpine
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD:-secret}
POSTGRES_DB: ${DB_NAME:-myapp}
volumes:
- pg-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
restart: unless-stopped
networks:
- backend
# dev 専用: Adminer DB UI
adminer:
image: adminer
ports:
- "8081:8080"
profiles: ["dev"]
networks:
- backend
volumes:
pg-data:
networks:
backend:
YAML
# ============================================
# docker-compose.prod.yml - 本番オーバーライド
# ============================================
services:
api:
deploy:
replicas: 3
resources:
limits:
cpus: "1.0"
memory: 512M
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
interval: 30s
timeout: 5s
retries: 3
nginx:
image: nginx:1.25-alpine
ports:
- "80:80"
volumes:
- ./nginx.prod.conf:/etc/nginx/conf.d/default.conf
depends_on:
api:
condition: service_healthy
restart: unless-stopped
networks:
- backend
BASH
# 開発
docker compose --profile dev up -d
# 本番(3 レプリカ + Nginx + リソース制限)
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# スケールの確認
docker compose -f docker-compose.yml -f docker-compose.prod.yml ps
❓ よくある質問
Q プロファイルと override ファイルは同時に使えますか?
A はい、使えます。
docker compose --profile dev -f docker-compose.yml -f docker-compose.dev.yml up -d のように、プロファイルと override ファイルを併用できます。プロファイルはサービスの追加・削除を管理し、override ファイルは設定の差分を管理する——両者は互いに補完し合います。Q
--scale と deploy.replicas のどちらが優先されますか?A コマンドラインの
--scale 引数が YAML の deploy.replicas より優先されます。両方が設定されている場合、--scale の値が YAML を上書きします。本番環境ではバージョン管理しやすい YAML 宣言を推奨し、デバッグ時の迅速な調整には --scale を使います。Q サービスの起動順序を制御するには?
A
depends_on + condition の組み合わせを使います。3 つの条件: ① service_started(デフォルト、起動のみ待つ)、② service_healthy(ヘルスチェック合格を待つ)、③ service_completed_successfully(初期化タスクの完了を待つ)。本番環境では常に service_healthy を使用してください。Q 環境ごとに Compose ファイルの変数を切り替えるには?
A
${VAR:-default} + .env ファイルを使います。各環境に異なる .env ファイル(.env.dev / .env.prod)を用意し、起動時に --env-file で指定します: docker compose --env-file .env.prod up -d。Q 複数レプリカでポートはどう扱いますか?
A スケール対象サービスはホストポートにマッピングできません(複数レプリカで競合するため)。Nginx / HAProxy のみポートを公開し、API サービスは内部ネットワークで通信します。Nginx の upstream が Docker DNS のラウンドロビンで複数レプリカに自動分散します。
📖 まとめ
- プロファイル: 同一ファイル内で環境ごとにサービスを追加・削除する。
--profile devで有効化 - override ファイル:
-f base.yml -f override.ymlでマージ。差分が大きい場合に適している - スケーリング:
--scale api=3またはdeploy.replicas: 3でステートレスサービスを水平スケール - スケール対象サービスはホストポートにマップしない——Nginx エントリーポイント + 内部 DNS ラウンドロビンを使う
deploy.resourcesで CPU / メモリの制限と予約を宣言するdepends_on: { condition: service_healthy }で依存サービスの真の準備完了を保証する
📝 練習問題
- 基本練習 (難易度 ⭐): 第 12 課のアプリケーションに対して、2 セットの override ファイル(dev 用と prod 用)を作成してください。dev 用にはホットリロード、prod 用にはリソース制限を追加します。
- 応用練習 (難易度 ⭐⭐):
--scale api=3で API サービスを 3 レプリカにスケールし、docker compose psで確認してください。 - 挑戦 (難易度: ⭐⭐⭐): 3 レプリカの API に対する Nginx リバースプロキシを設定し、リクエストが異なるレプリカに分散されることを(各コンテナのログで)確認してください。