Docker: 第 3 フェーズ統合実践

最終更新:2026-08-26

第 3 フェーズのコンセプトを統合する——マイクロサービスベースの EC プラットフォームバックエンドを完成させます。

1. 学べること



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) アーキテクチャ概要

100%
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 ではサービス名(postgresredis など)を使うことを推奨します。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 で再起動します。

📖 まとめ


📝 練習問題

  1. 基本問題 (難易度: ⭐): ブログシステム向けのマルチサービスアーキテクチャ(Nginx + API + DB + Cache)を設計し、docker-compose.yml を作成してシステムを起動してください。
  2. 応用練習 (難易度: ⭐⭐): API を複数レプリカ(replicas: 3)に設定し Nginx 負荷分散を構築、リクエストが異なるレプリカへ分散されることを確認してください。
  3. 挑戦 (難易度: ⭐⭐⭐): dev 用と prod 用の 2 セットの override ファイル(dev: Adminer とホットリロードを追加、prod: リソース制限とログローテーションを追加)を作成し、それぞれの環境で起動して差分を確認してください。
Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%