Featured image of post 開発環境から本番環境まで共通化するDocker Compose構成設計 Featured image of post 開発環境から本番環境まで共通化するDocker Compose構成設計

開発環境から本番環境まで共通化するDocker Compose構成設計

Docker Composeを開発環境から本番環境まで共通化するベストプラクティスを解説。docker-compose.override.ymlやプロファイル、環境変数を活用し、ローカル開発と本番運用の設定を安全に切り替える実践的な構成設計手法を学びます。

開発環境から本番環境まで共通化するDocker Compose構成設計

Docker Composeはマルチコンテナアプリケーションを定義・実行するための標準ツールです。しかし多くのチームは、開発用、ステージング用、本番用に個別のdocker-compose.ymlファイルを管理する罠に陥り、重複、設定の乖離、設定バグを引き起こしています。

より良いアプローチは、Composeファイルのオーバーレイプロファイル環境変数を活用して、各環境に適応する単一の情報源を維持することです。


基本となる compose.yml パターン

まず、環境間で共通するサービス定義(イメージ、コマンド、ポート、環境変数)を記述した単一のcompose.ymlから始めます。

# compose.yml
services:
  app:
    image: myapp:${APP_VERSION:-latest}
    build:
      context: .
      target: ${BUILD_TARGET:-development}
    ports:
      - "${APP_PORT:-3000}:3000"
    environment:
      - NODE_ENV=${NODE_ENV:-development}
      - DATABASE_URL=${DATABASE_URL}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASS}
      POSTGRES_DB: ${DB_NAME}
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  pgdata:

環境変数はデフォルト値付き(${VAR:-default})で使用し、基本ファイルをジェネリックに保ちます。


compose.override.yml による環境オーバーライド

Docker Composeはcompose.override.ymlが存在すれば自動的に読み込みます。これは開発専用の設定に使用します — 本番環境に影響を与えるオーバーライドは絶対にコミットしないでください。

# compose.override.yml(本番環境では除外)
services:
  app:
    build:
      target: development
    volumes:
      - .:/app
      - /app/node_modules
    ports:
      - "9229:9229" # デバッガ
    environment:
      - NODE_ENV=development
      - DEBUG=app:*
    command: npm run dev

  db:
    ports:
      - "5432:5432" # ローカルツール用に公開
    volumes:
      - ./scripts/seed:/docker-entrypoint-initdb.d

本番環境では、別のオーバーライドファイルを使用します。

# compose.prod.yml
services:
  app:
    build:
      target: production
    restart: always
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 1G
        reservations:
          cpus: '0.5'
          memory: 256M
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

デプロイは次のコマンドで行います。docker compose -f compose.yml -f compose.prod.yml up -d


プロファイルによる環境バリアントの使い分け

プロファイル(Docker Compose 2.0+)を使用すると、環境に基づいてサービスを条件付きで有効化できます。

services:
  mailhog:
    image: mailhog/mailhog
    profiles: ["development", "staging"]
    ports:
      - "8025:8025"

  redis:
    image: redis:7-alpine
    profiles: ["development", "staging", "production"]

  redis-commander:
    image: rediscommander/redis-commander
    profiles: ["development"]
    ports:
      - "8081:8081"

docker compose --profile development up を実行すると、開発に関連するサービスだけが起動します。


ヘルスチェックと再起動ポリシー

サポートしているすべてのサービスにヘルスチェックを定義します。再起動ポリシーと組み合わせることで、自己修復型のデプロイを実現します。

services:
  app:
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "wget", "--spider", "http://localhost:3000/health"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 40s

  worker:
    restart: on-failure:5
    depends_on:
      app:
        condition: service_healthy

depends_on.condition: service_healthy により、アプリがヘルスチェックに合格するまでワーカーは起動しません。


リソース制限とスケーリング

リソース制限を設定して、暴走したコンテナがホスト全体をダウンさせるのを防ぎます。

services:
  app:
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 128M

  worker:
    deploy:
      mode: replicated
      replicas: 3
      resources:
        limits:
          cpus: '2'
          memory: 1G

注意:deploy設定はDocker SwarmおよびCompose v3スタックに適用されます。通常のdocker composeでは、--compatibilityフラグを使用するか、プラットフォーム固有の制限を使用します。


シークレット管理

シークレットをComposeファイルにハードコードしてはいけません。Dockerシークレットまたはアクセス権限を制限した環境変数ファイルを使用します。

# Dockerシークレットの使用(Swarmモード)
secrets:
  db_password:
    file: ./secrets/db_password.txt

services:
  app:
    secrets:
      - db_password
    environment:
      - DATABASE_URL=postgres://user:${DB_PASSWORD}@db:5432/myapp

非Swarm環境では、.envファイルを使用します。

# .env(バージョン管理には絶対にコミットしない)
DB_USER=myapp
DB_PASS=s3cret!
DB_NAME=myapp
APP_PORT=3000

ログ設定

集中ロギングにより、コンテナのログスパムによるディスク容量の枯渇を防ぎます。

services:
  app:
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  # リモートログサービスへの転送
  log-collector:
    logging:
      driver: "fluentd"
      options:
        fluentd-address: "localhost:24224"
        tag: "docker.{{.Name}}"

まとめ

再利用可能なDocker Compose構成の設計とは、関心の分離です。基本のcompose.ymlで共通定義を、オーバーライドファイルで環境固有の設定を、プロファイルで条件付きサービスを、環境変数でシークレットと設定を管理します。

この階層的アプローチにより、重複が排除され、設定の乖離が減少し、開発・ステージング・本番を通じて予測可能なデプロイパイプラインが実現します。これらのパターンを採用して、自信を持ってデプロイしましょう。