Docker: 総合実践トレーニング

最終更新:2026-08-26

これは本コースの最終プロジェクトです。全 23 レッスンの知識を結集し、フルスタックマイクロサービスをゼロから本番環境までデプロイします。

1. 学べること



2. 3 日納品の物語

(1) 挑戦: 3 日以内にローカルから本番へ

Charlie はタスクを任されました。3 日以内に EC プラットフォームをローカル開発から本番環境へデプロイすることです。アーキテクチャは React フロントエンド、Go API、PostgreSQL、Redis、RabbitMQ の 5 サービス。手動の自動化プロセスは一切ありません。

(2) Docker フルスタックツールチェーンによるソリューション

Charlie はフルスタックの Docker ツールチェーンを使い、わずか 2 日でプロジェクトを完成させました。Dockerfile の作成 → Compose でのオーケストレーション → 自動化された CI/CD デプロイ → 監視とアラート。

(3) 効果: 2 日で完成・納品

手動デプロイから完全自動化へ。アーキテクチャ設計、コンテナ化、オーケストレーション、CI/CD、監視をわずか 2 日で完了——これがフルスタック Docker スキルをマスターする価値です。



3. フルスタックアーキテクチャ設計

(1) アーキテクチャ概要

100%
graph TB
    USER["ブラウザ"] --> ING["Nginx<br/>:80<br/>React SPA + API プロキシ"]
    ING -->|"api/"| API1["Go API #1<br/>:8080"]
    ING -->|"api/"| API2["Go API #2<br/>:8080"]
    ING -->|"api/"| API3["Go API #3<br/>:8080"]
    API1 --> PG["PostgreSQL<br/>:5432<br/>プライマリ DB"]
    API2 --> PG
    API3 --> PG
    API1 --> REDIS["Redis<br/>:6379<br/>キャッシュ"]
    API2 --> REDIS
    API3 --> MQ["RabbitMQ<br/>:5672<br/>メッセージキュー"]
    MQ --> WRK["Worker<br/>バックグラウンドジョブ"]
    PROM["Prometheus<br/>:9090<br/>メトリクス"] --> GRAF["Grafana<br/>:3000<br/>ダッシュボード"]
    PROM --> API1
    PROM --> PG
    PROM --> REDIS

(2) サービス一覧

サービス 技術スタック イメージ ポート
Nginx リバースプロキシ + 静的ファイル セルフホスト (マルチステージ) 80
Go API REST API セルフホスト (マルチステージ) 8080
PostgreSQL リレーショナルデータベース postgres:15-alpine 5432
Redis キャッシュ + セッション redis:7-alpine 6379
RabbitMQ メッセージキュー rabbitmq:3-management 5672/15672
Worker バックグラウンドタスク処理 セルフホスト (API イメージと共通) -
Prometheus メトリクス収集 prom/prometheus 9090
Grafana 可視化ダッシュボード grafana/grafana 3000


4. フロントエンド Dockerfile (React + Nginx)

▶ サンプル: フロントエンド Dockerfile のマルチステージビルド (難易度: ⭐⭐⭐)

DOCKERFILE
# ============================================
# ステージ 1: React アプリケーションをビルド
# ============================================
FROM node:20-alpine AS builder

WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# ============================================
# ステージ 2: Nginx で配信
# ============================================
FROM nginx:1.25-alpine

# ビルド成果物をコピー
COPY --from=builder /app/dist /usr/share/nginx/html

# SPA ルーティング用の Nginx 設定をコピー
COPY nginx.conf /etc/nginx/conf.d/default.conf

# セキュリティ: root 以外のユーザー
RUN chown -R nginx:nginx /usr/share/nginx/html && \
    chown -R nginx:nginx /var/cache/nginx && \
    chown -R nginx:nginx /var/log/nginx

EXPOSE 80
HEALTHCHECK --interval=30s --timeout=5s \
  CMD wget -qO- http://localhost/ || exit 1

CMD ["nginx", "-g", "daemon off;"]


5. バックエンド Dockerfile (Go マルチステージ)

▶ サンプル: バックエンド Dockerfile のマルチステージビルド (難易度: ⭐⭐⭐)

DOCKERFILE
# ============================================
# ステージ 1: Go バイナリをビルド
# ============================================
FROM golang:1.22-alpine AS builder

RUN apk add --no-cache git

WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o /app/server

# ============================================
# ステージ 2: 最小限のランタイム
# ============================================
FROM alpine:3.19

RUN apk --no-cache add ca-certificates tzdata curl && \
    adduser -D -u 1000 appuser

WORKDIR /app
COPY --from=builder /app/server .

RUN chown -R appuser:appuser /app
USER appuser

EXPOSE 8080

HEALTHCHECK --interval=15s --timeout=5s --start-period=10s --retries=3 \
  CMD curl -f http://localhost:8080/health || exit 1

CMD ["/app/server"]


6. Docker Compose オーケストレーション

▶ サンプル: 完全な docker-compose.prod.yml (難易度: ⭐⭐⭐)

YAML
# ============================================
# docker-compose.prod.yml - フルスタック
# ============================================
services:
  nginx:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - "80:80"
    depends_on:
      api:
        condition: service_healthy
    restart: unless-stopped
    networks:
      - frontend
      - backend
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "5"

  api:
    build:
      context: ./api
      dockerfile: Dockerfile
    environment:
      DATABASE_URL: postgresql://appuser:${DB_PASSWORD}@postgres:5432/${DB_NAME}
      REDIS_URL: redis://redis:6379
      RABBITMQ_URL: amqp://guest:${MQ_PASSWORD}@rabbitmq:5672
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: "1.0"
          memory: 512M
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    restart: unless-stopped
    networks:
      - backend
      - db-net
      - cache-net
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 15s
      timeout: 5s
      retries: 3
      start_period: 10s
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "5"

  worker:
    build:
      context: ./api
      dockerfile: Dockerfile
    command: ["/app/server", "worker"]
    environment:
      DATABASE_URL: postgresql://appuser:${DB_PASSWORD}@postgres:5432/${DB_NAME}
      RABBITMQ_URL: amqp://guest:${MQ_PASSWORD}@rabbitmq:5672
    depends_on:
      postgres:
        condition: service_healthy
      rabbitmq:
        condition: service_healthy
    restart: unless-stopped
    networks:
      - backend
      - db-net

  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: appuser
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: ${DB_NAME}
    volumes:
      - pg-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U appuser"]
      interval: 5s
      timeout: 5s
      retries: 5
    restart: unless-stopped
    networks:
      - db-net

  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
    volumes:
      - redis-data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
      interval: 10s
      timeout: 5s
    restart: unless-stopped
    networks:
      - cache-net

  rabbitmq:
    image: rabbitmq:3-management-alpine
    environment:
      RABBITMQ_DEFAULT_PASS: ${MQ_PASSWORD}
    ports:
      - "15672:15672"
    volumes:
      - mq-data:/var/lib/rabbitmq
    healthcheck:
      test: ["CMD", "rabbitmq-diagnostics", "check_port_connectivity"]
      interval: 15s
      timeout: 10s
    restart: unless-stopped
    networks:
      - backend

  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus-data:/prometheus
    ports:
      - "9090:9090"
    restart: unless-stopped
    networks:
      - backend
      - db-net
      - cache-net

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    environment:
      GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD}
    volumes:
      - grafana-data:/var/lib/grafana
    depends_on:
      - prometheus
    restart: unless-stopped
    networks:
      - backend

volumes:
  pg-data:
  redis-data:
  mq-data:
  prometheus-data:
  grafana-data:

networks:
  frontend:
  backend:
  db-net:
    internal: true
  cache-net:
    internal: true


7. CI/CD 設定

(1) GitHub Actions フルパイプライン

YAML
# .github/workflows/deploy.yml
name: Build and Deploy

on:
  push:
    branches: [main]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: docker/setup-buildx-action@v3

      - uses: docker/login-action@v3
        with:
          registry: ${{ secrets.REGISTRY }}
          username: ${{ secrets.REGISTRY_USER }}
          password: ${{ secrets.REGISTRY_PASS }}

      - name: API をビルドしてプッシュ
        uses: docker/build-push-action@v5
        with:
          context: ./api
          push: true
          tags: ${{ secrets.REGISTRY }}/api:${{ github.sha }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: フロントエンドをビルドしてプッシュ
        uses: docker/build-push-action@v5
        with:
          context: ./frontend
          push: true
          tags: ${{ secrets.REGISTRY }}/frontend:${{ github.sha }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: 本番環境へデプロイ
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_KEY }}
          script: |
            cd /opt/ecommerce
            export API_TAG=${{ github.sha }}
            export FRONTEND_TAG=${{ github.sha }}
            docker compose -f docker-compose.prod.yml pull
            docker compose -f docker-compose.prod.yml up -d --remove-orphans
            docker image prune -f


8. 監視設定

(1) Prometheus 設定

YAML
# monitoring/prometheus.yml
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'api'
    static_configs:
      - targets: ['api:8080']
    metrics_path: /metrics

  - job_name: 'postgres'
    static_configs:
      - targets: ['postgres-exporter:9187']

  - job_name: 'redis'
    static_configs:
      - targets: ['redis-exporter:9121']

  - job_name: 'rabbitmq'
    static_configs:
      - targets: ['rabbitmq:15692']


9. デプロイと検証

(1) デプロイチェックリスト

ステップ アクション 検証
1 docker compose -f docker-compose.prod.yml up -d --build docker compose ps ですべて Up
2 http://localhost にアクセス React ページが正常に表示される
3 curl http://localhost/api/health {"ステータス":"ok"}
4 http://localhost:3000 にアクセス Grafana ログインページ
5 http://localhost:15672 にアクセス RabbitMQ 管理ページ
6 docker compose logs api API ログにエラーがない

(2) 比較表: ベアメタル vs Docker vs K8s

ディメンション ベアメタルデプロイ Docker Compose Kubernetes
デプロイ時間 1〜2 日 30 分 1〜2 日 (初期セットアップ)
再現性
自動スケーリング ✅ HPA
セルフヒーリング 再起動ポリシー ✅ 自動再構築
ゼロダウンタイム更新 困難 Compose 再起動 ✅ ローリングアップデート
監視 手動 Prometheus + Grafana 組み込み + Prometheus
複雑性


10. 完全なサンプル: ワンクリックでフルスタックアプリをデプロイ

BASH
# ============================================
# 完全な手順: フルスタックデプロイ
# ============================================

# 1. .env ファイルを作成 (絶対にコミットしないこと)
cat > .env << 'EOF'
DB_PASSWORD=secure_db_pass_2024
DB_NAME=ecommerce
REDIS_PASSWORD=secure_redis_pass
MQ_PASSWORD=secure_mq_pass
GRAFANA_PASSWORD=admin123
EOF

# 2. すべてのサービスをビルドして起動
docker compose -f docker-compose.prod.yml up -d --build

# 3. サービスの初期化を待つ
sleep 30

# 4. すべてのサービスを検証
docker compose -f docker-compose.prod.yml ps
echo "=== ヘルスチェック ==="
docker compose -f docker-compose.prod.yml ps --format "table {{.Name}}\t{{.Status}}"

# 5. API をテスト
curl -s http://localhost/api/health

# 6. データベース接続を確認
docker compose -f docker-compose.prod.yml exec postgres pg_isready -U appuser

# 7. 監視にアクセス
echo "Grafana: http://localhost:3000 (admin/${GRAFANA_PASSWORD})"
echo "RabbitMQ: http://localhost:15672 (guest/${MQ_PASSWORD})"
echo "Prometheus: http://localhost:9090"

# 8. 集約ログを確認
docker compose -f docker-compose.prod.yml logs --tail 50 api

# 9. 必要に応じて API をスケール
docker compose -f docker-compose.prod.yml up -d --scale api=5

# 10. クリーンアップ
docker compose -f docker-compose.prod.yml down

❓ よくある質問

Q マイクロサービスはモノリシックアーキテクチャと比べてどれくらい複雑ですか?
A 運用面の複雑性は大幅に増します。ネットワーク構成、サービス検出、ログ集約、分散トレーシングなど新たな課題が生じます。ただしメリットには、独立したデプロイ、独立したスケーリング、障害の分離があります。推奨: 小規模チーム (5 人未満) はモジュール式モノリス、大規模チームはマイクロサービスを採用してください。マイクロサービスは手段のために採用しないでください。
Q CI/CD でデータベースマイグレーションはどのように実行しますか?
A デプロイステップの前にマイグレーションステップを追加します。① マイグレーションイメージをビルド。② docker run --rm migrate:latest alembic upgrade head。③ 新バージョンをデプロイ。重要ポイント: マイグレーションは後方互換性を持たせる必要があります。新コードは新旧両方のテーブル構造をサポートしなければなりません。
Q 複数サービスのログを統合するにはどうすればよいですか?
A 3 つのアプローチがあります。① ELK Stack (Elasticsearch + Logstash + Kibana) — 業界標準。② Loki + Grafana (軽量、クラウドネイティブ環境向け)。③ クラウドプロバイダーのロギングサービス (AWS CloudWatch / Alibaba Cloud SLS)。すべてのコンテナの stdout → コレクター → 一元ストレージ → 検索ダッシュボード。
Q 本番環境で HTTPS を設定するには?
A Nginx コンテナで TLS を設定します。① 無料の Let's Encrypt 証明書 + Certbot で自動更新。② リバースプロキシモード: Nginx が TLS を処理し、内部通信は HTTP を使用。③ クラウドプロバイダーのロードバランサーが TLS を処理 (ALB / SLB) する場合、コンテナに証明書は不要。
Q マイクロサービススタック全体の健全性を監視するには?
A Prometheus と Grafana のゴールデンコンボです。① Prometheus が各サービスの /メトリクス エンドポイントからデータを収集。② Grafana がダッシュボードとアラートルールを表示。③ 主要メトリクス: API レイテンシ (P50 / P95 / P99)、エラー率、CPU / メモリ使用率、データベース接続数。まず監視し、それから最適化しましょう。

📖 まとめ


📝 練習問題

  1. 基礎問題 (難易度: ⭐): ブログシステム (Nginx + API + DB + キャッシュ) のマイクロサービスアーキテクチャ図を設計し、各サービスのイメージとポートを列挙してください。
  2. 応用問題 (難易度: ⭐⭐): フルスタック Docker 技術を使ってこのアーキテクチャをデプロイし、docker-compose.prod.yml ファイルを作成、アプリケーションを正常に起動してください。
  3. 挑戦問題 (難易度: ⭐⭐⭐): Prometheus + Grafana 監視ダッシュボードをセットアップし、API レイテンシとエラー率用のダッシュボードを追加、メールアラートルールを設定してください。
Web-Tutorial.com

Web-Tutorial 技術チーム

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

100%