Docker: 第 3 フェーズ統合実践
最終更新:2026-08-26
第 3 フェーズのコンセプトを統合する——マイクロサービスベースの EC プラットフォームバックエンドを完成させます。
1. 学べること
- 多層 Compose プロジェクト構造の設計
- サービス検出と負荷分散
- データ永続化戦略
- 複数環境での設定管理
- ヘルスチェックとセルフヒーリング
2. EC プラットフォームバックエンド誕生のストーリー
(1) 悩み: 手動起動が必要な 6 つのサービス
Charlie は EC プラットフォームバックエンド用に 6 つのサービスをデプロイする必要があります: React フロントエンド、Nginx リバースプロキシ、Go API、PostgreSQL、Redis キャッシュ、RabbitMQ メッセージキュー。docker run を手動で使うには 30 以上のパラメーターを覚える必要があり、起動順序も厳密なのでエラー率が極めて高くなります。
(2) ワンクリック構成のソリューション
Charlie はすべてを 1 つの docker-compose.yml ファイルで処理しました。
BASH
docker compose up -d
(3) 効果: 6 サービスの一発起動
手動 30 分から docker compose up -d の 30 秒へ短縮。新人メンバーでも 5 分でバックエンド全体を起動できます。
3. マイクロサービスアーキテクチャの設計
(1) アーキテクチャ概要
graph TB
USER["ブラウザ"] --> NGX["Nginx<br/>:80 リバースプロキシ"]
NGX -->|"api/"| API1["Go API #1<br/>:8080"]
NGX -->|"api/"| API2["Go API #2<br/>:8080"]
NGX -->|"api/"| API3["Go API #3<br/>:8080"]
NGX -->|"/"| REACT["React SPA<br/>静的ファイル"]
API1 --> PG["PostgreSQL<br/>:5432"]
API2 --> PG
API3 --> PG
API1 --> REDIS["Redis<br/>:6379"]
API2 --> REDIS
API3 --> MQ["RabbitMQ<br/>:5672"]
(2) サービス一覧
| サービス | イメージ | ポート | ネットワーク | 依存関係 |
|---|---|---|---|---|
| Nginx | nginx:1.25-alpine | 80→80 | フロントエンド, バックエンド | api (healthy) |
| React | セルフホスト(マルチステージ) | - | フロントエンド | - |
| Go API | セルフビルド(マルチステージ) | 8080 | バックエンド, db-net, キャッシュ-net | postgres (healthy), redis |
| PostgreSQL | postgres:15-alpine | 5432 | db-net | - |
| Redis | redis:7-alpine | 6379 | キャッシュ-net | - |
| RabbitMQ | rabbitmq:3-management | 5672, 15672 | バックエンド | - |
4. Compose ファイルの作成
▶ サンプル: 完全な compose ファイルの作成 (難易度: ⭐⭐⭐)
YAML
# ============================================
# docker-compose.yml - EC マイクロサービス
# ============================================
services:
# ---------- フロントエンド ----------
nginx:
image: nginx:1.25-alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
- react-build:/usr/share/nginx/html:ro
depends_on:
api:
condition: service_healthy
restart: unless-stopped
networks:
- frontend
- backend
healthcheck:
test: ["CMD", "nginx", "-t"]
interval: 30s
timeout: 5s
react:
build:
context: ./frontend
dockerfile: Dockerfile
volumes:
- react-build:/app/build
networks:
- frontend
# ---------- バックエンド ----------
api:
build:
context: ./api
dockerfile: Dockerfile
environment:
DATABASE_URL: postgresql://appuser:${DB_PASSWORD:-secret}@postgres:5432/${DB_NAME:-ecommerce}
REDIS_URL: redis://redis:6379
RABBITMQ_URL: amqp://guest:guest@rabbitmq:5672
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_started
restart: unless-stopped
deploy:
replicas: 3
resources:
limits:
cpus: "1.0"
memory: 512M
networks:
- backend
- db-net
- cache-net
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:8080/health"]
interval: 15s
timeout: 5s
retries: 3
start_period: 10s
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
# ---------- データストア ----------
postgres:
image: postgres:15-alpine
environment:
POSTGRES_USER: appuser
POSTGRES_PASSWORD: ${DB_PASSWORD:-secret}
POSTGRES_DB: ${DB_NAME:-ecommerce}
volumes:
- pg-data:/var/lib/postgresql/data
restart: unless-stopped
networks:
- db-net
healthcheck:
test: ["CMD-SHELL", "pg_isready -U appuser"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
command: redis-server --appendonly yes
volumes:
- redis-data:/data
restart: unless-stopped
networks:
- cache-net
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
rabbitmq:
image: rabbitmq:3-management-alpine
ports:
- "15672:15672" # 管理 UI
environment:
RABBITMQ_DEFAULT_USER: guest
RABBITMQ_DEFAULT_PASS: guest
volumes:
- mq-data:/var/lib/rabbitmq
restart: unless-stopped
networks:
- backend
# ---------- ボリューム ----------
volumes:
pg-data:
redis-data:
mq-data:
react-build:
# ---------- ネットワーク ----------
networks:
frontend:
backend:
db-net:
internal: true # 外部アクセス不可
cache-net:
internal: true
(1) Nginx 設定 (負荷分散)
TEXT
📖 参照専用
# nginx.conf
upstream api_backend {
server api:8080; # 3 レプリカへ Docker DNS ラウンドロビン
}
server {
listen 80;
server_name localhost;
# 静的ファイル(React SPA)
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
}
# API プロキシ
location /api/ {
proxy_pass http://api_backend/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
5. 複数環境の設定
▶ サンプル: 開発環境でのオーバーライド (難易度: ⭐⭐)
YAML
# docker-compose.dev.yml
services:
api:
build:
context: ./api
dockerfile: Dockerfile.dev
volumes:
- ./api/src:/app/src # ホットリロード
environment:
GO_ENV: development
deploy:
replicas: 1 # デバッグ用に単一レプリカ
# dev 専用: データベース管理 UI
adminer:
image: adminer
ports:
- "8081:8080"
profiles: ["dev"]
networks:
- db-net
6. ヘルスチェックとセルフヒーリング
▶ サンプル: 全サービスにヘルスチェックを追加 (難易度: ⭐⭐)
YAML
# 各サービスのヘルスチェック設定
services:
api:
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://localhost:8080/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 20s
postgres:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER"]
interval: 5s
timeout: 3s
retries: 5
redis:
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 3
出力:
NAME STATUS ecommerce-api-1 Up 2 minutes (healthy) ecommerce-postgres Up 2 minutes (healthy) ecommerce-redis-1 Up 2 minutes (healthy)
7. デプロイの検証
(1) 検証チェックリスト
| テスト項目 | コマンド | 期待結果 |
|---|---|---|
| 全サービスが実行中 | docker compose ps |
6+ サービス up |
| Nginx 正常 | curl http://localhost |
200 OK |
| API ヘルス | curl http://localhost/api/health |
{"ステータス":"ok"} |
| API レプリカ数 | docker compose ps api |
3 コンテナ |
| Redis 接続 | docker compose exec redis redis-cli ping |
PONG |
| PostgreSQL 接続 | docker compose exec postgres pg_isready |
accepting connections |
| データベース分離 | Nginx コンテナから Postgres に ping | 失敗(内部ネットワーク) |
8. 完全なサンプル: EC プラットフォームのワンクリックデプロイ
BASH
# ============================================
# 完全なウォークスルー: EC マイクロサービス
# ============================================
# 1. 全サービスをビルドして起動
docker compose up -d --build
# 2. 全サービスが動作中か確認
docker compose ps
# 3. ヘルスステータスを確認
docker compose ps --format "table {{.Name}}\t{{.Status}}"
# 4. API をテスト
curl -s http://localhost/api/health | python3 -m json.tool
# 5. 負荷分散を確認(複数リクエストで異なるレプリカへ)
for i in $(seq 1 6); do
curl -s http://localhost/api/health | jq -r '.hostname'
done
# 6. API からデータベース接続を確認
docker compose exec api wget -qO- http://localhost:8080/health
# 7. RabbitMQ 管理 UI にアクセス
# ブラウザで http://localhost:15672 を開く (guest/guest)
# 8. ログを表示
docker compose logs -f api
# 9. API を 5 レプリカにスケール
docker compose up -d --scale api=5
# 10. クリーンアップ
docker compose down
docker compose down -v # データボリュームも削除
❓ よくある質問
Q サービス間の通信にはネットワークエイリアスとサービス名のどちらを使うべきですか?
A Compose ではサービス名(
postgres、redis など)を使うことを推奨します。Compose は自動的に各サービスの DNS レコードを登録し、サービス名がそのままホスト名になります。ネットワークエイリアスは、同一サービスがネットワークごとに異なる名前を必要とするケースで使います。Q 依存関係の起動順序はどのように保証しますか?
A
depends_on + condition: service_healthy の組み合わせを使います。API は postgres のヘルスチェック合格後にのみ起動します。注意: depends_on: [db](デフォルトの 条件分岐: service_started)はコンテナの起動を待つだけで、サービスの準備完了は待ちません。Q 複数インスタンスの API は負荷分散をどう扱いますか?
A Docker 組み込みの DNS ラウンドロビン + Nginx upstream です。3 つの API コンテナはすべて
api という DNS 名で登録され、Nginx の upstream api_backend { server api:8080; } がリクエストをラウンドロビンします。より複雑な負荷分散戦略が必要なら HAProxy も検討できます。Q データベースのマスタースレーブレプリケーションを設定するには?
A 単一ノードの Compose では、マスタースレーブを設定した複数 PostgreSQL コンテナを使うことができます。ただし本番品質のマスタースレーブには、マネージドデータベース(AWS RDS / クラウドプロバイダ)または専用ツール(Patroni / Stolon)の利用を推奨します。本レッスンの PostgreSQL インスタンスは単一ノードです。
Q ホットリロードはどのように実装しますか?
A 開発環境ではボリュームでソースコードをマウントし(例:
-v ./api/src:/app/src)、ホットリロードツール(Go は air、Node は nodemon、Python は flask --debugなど)を使います。本番環境ではソースコードをマウントせず、環境変数で設定変更し docker compose up -d で再起動します。📖 まとめ
- マイクロサービス Compose アーキテクチャ: フロントエンド → バックエンド → データストアの 3 層ネットワーク分離
internal: trueでネットワーク経由でデータベース / キャッシュへの外部直接アクセスを防止- 複数 API レプリカと Nginx upstream で負荷分散
depends_on: { condition: service_healthy }で依存関係の真の準備完了を保証- ログローテーション
logging: { options: { max-size: "10m" } }でディスク満杯を防止 - dev / prod 環境間の差分は override ファイルで管理
📝 練習問題
- 基本問題 (難易度: ⭐): ブログシステム向けのマルチサービスアーキテクチャ(Nginx + API + DB + Cache)を設計し、
docker-compose.ymlを作成してシステムを起動してください。 - 応用練習 (難易度: ⭐⭐): API を複数レプリカ(replicas: 3)に設定し Nginx 負荷分散を構築、リクエストが異なるレプリカへ分散されることを確認してください。
- 挑戦 (難易度: ⭐⭐⭐): dev 用と prod 用の 2 セットの override ファイル(dev: Adminer とホットリロードを追加、prod: リソース制限とログローテーションを追加)を作成し、それぞれの環境で起動して差分を確認してください。