Docker Compose本番環境での使い方完全ガイド|安全な運用と設定のポイント

kento_morota 13分で読めます

Docker Composeは本番環境で使えるのか?

「Docker Composeって開発環境専用のツールじゃないの?」という疑問を持つ方は少なくありません。結論から言えば、Docker Composeは本番環境でも十分に使えます。特に中小規模のシステムでは、複雑なツールより、シンプルで管理しやすいDocker Composeの方が適しています。

Docker Composeの適用範囲を正しく理解する

Docker Composeが「開発専用」という誤解が広まった背景には、大規模システムの事例でKubernetesが紹介されることが多く、「本番環境=Kubernetes」というイメージが定着したことがあります。しかし実際には、システムの規模や要件によって適切なツールは異なります。

Docker Composeが適している場面:

  • 単一サーバーまたは少数のサーバーで運用するシステム
  • 月間数万〜数十万PV程度のWebサイト
  • 社内向けの業務システムや管理ツール
  • IT担当者が1〜3名程度の組織

Kubernetesを検討すべき場面:

  • 複数サーバーにまたがる大規模分散システム
  • 自動スケーリングが頻繁に必要なシステム
  • 専任のインフラエンジニアチームがいる組織

中小企業にDocker Composeが適している理由は3つあります。学習コストの低さ(数日で基本運用が可能)、運用コストの削減(1台のVPSで運用可能)、トラブルシューティングの容易さ(設定ファイルを見れば原因を特定しやすい)です。月間10万PV程度のWebサービスなら、Docker Composeで十分に安定稼働できます。

開発環境と本番環境の設定を分離する

Docker Composeを本番環境で使う際の最初のステップは、環境ごとの設定を適切に分離することです。同じ設定を両環境で使うと、セキュリティリスクや予期しない動作の原因になります。

複数のComposeファイルによる環境管理

Docker Composeは複数のYAMLファイルを自動的にマージする機能があり、これを活用して環境を分離します。

推奨ファイル構成:

project/
├── docker-compose.yml          # 基本設定(共通)
├── docker-compose.override.yml # 開発環境用(自動読み込み)
├── docker-compose.prod.yml     # 本番環境用
└── .env.example                # 環境変数テンプレート

docker-compose.yml(基本設定):

version: '3.8'
services:
  web:
    image: myapp:${APP_VERSION}
    networks:
      - app-network
    depends_on:
      - db
  db:
    image: postgres:14
    volumes:
      - db-data:/var/lib/postgresql/data
    networks:
      - app-network
networks:
  app-network:
volumes:
  db-data:

docker-compose.override.yml(開発環境):

version: '3.8'
services:
  web:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - ./src:/app/src  # ホットリロード用
    environment:
      - NODE_ENV=development
  db:
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_PASSWORD=devpassword

docker-compose.prod.yml(本番環境):

version: '3.8'
services:
  web:
    restart: always
    environment:
      - NODE_ENV=production
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 1G
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
  db:
    restart: always
    environment:
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

開発環境ではdocker-compose upだけで起動でき、本番環境では以下のコマンドを使います。

docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

環境変数による機密情報の管理

パスワードやAPIキーは.envファイルで管理し、Gitにコミットしません。

.env.example(テンプレート):

APP_VERSION=1.0.0
DB_PASSWORD=your_secure_password_here
SECRET_KEY=your_secret_key_here

.gitignore:

.env
.env.*
!.env.example

本番環境では、サーバー上で.envファイルを作成し、権限を制限します。

cp .env.example .env
vi .env  # 実際の値を設定
chmod 600 .env

本番環境向けの必須設定

本番環境でDocker Composeを安全に運用するには、開発環境とは異なる設定が必要です。

開発環境の設定を削除する

以下の設定は本番環境から削除します。

  1. ソースコードのボリュームマウント./src:/app/src
  2. 内部サービスのポート公開(データベースなど)
  3. デバッグモードの環境変数

また、イメージタグはlatestではなく具体的なバージョン(myapp:1.2.3)を指定します。

自動再起動の設定

本番環境で最も重要な設定の一つがrestartポリシーです。

services:
  web:
    restart: always
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

restart: alwaysにより、コンテナのクラッシュやサーバー再起動時に自動的に復旧します。ヘルスチェックと組み合わせることで、起動失敗の無限ループを防げます。

リソース制限の設定

リソース制限がないと、メモリリークでサーバー全体がダウンする可能性があります。

services:
  web:
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 1G
        reservations:
          cpus: '0.5'
          memory: 512M

サーバーの総リソースを考慮し、すべてのコンテナのlimits合計が容量を超えないよう設定します。

ログローテーションの設定

デフォルトではログが無制限に蓄積されます。必ずログローテーションを設定しましょう。

services:
  web:
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
        compress: "true"

この設定で、ログは最大30MB(10MB × 3ファイル)までに制限されます。

セキュリティ対策

機密情報の保護

パスワードやAPIキーをdocker-compose.ymlに直接書かないことが最重要です。必ず環境変数(${DB_PASSWORD})で参照し、実際の値は.envファイルに記述します。

# ❌ 悪い例
environment:
  - POSTGRES_PASSWORD=my_secret_password

# ⭕ 良い例
environment:
  - POSTGRES_PASSWORD=${DB_PASSWORD}

ネットワークの分離とポート制限

コンテナ間通信は適切にネットワークを分離します。

services:
  web:
    networks:
      - frontend
      - backend
    ports:
      - "80:3000"  # 外部公開
  db:
    networks:
      - backend
    expose:
      - "5432"  # コンテナ間のみ
networks:
  frontend:
  backend:

データベースはexposeを使い、コンテナ間通信のみ許可します。portsは外部に公開されるため、内部サービスには使いません。

サーバーレベルでもファイアウォールを設定します。

sudo ufw allow 22/tcp    # SSH
sudo ufw allow 80/tcp    # HTTP
sudo ufw allow 443/tcp   # HTTPS
sudo ufw deny 5432/tcp   # PostgreSQL
sudo ufw enable

イメージのバージョン管理

# ❌ 予期しない変更が入る可能性
image: node:latest

# ⭕ 具体的なバージョンを指定
image: node:18.17.1

バージョンを固定したら、定期的にセキュリティアップデートを確認し、計画的に更新します。脆弱性スキャンツール(Trivy、Docker Scanなど)を活用しましょう。

trivy image myapp:1.2.3

本番環境へのデプロイと運用

デプロイの基本手順

  1. イメージのビルドとプッシュ
docker build -t myapp:1.2.3 .
docker push myapp:1.2.3
  1. 本番環境での更新
# 最新イメージを取得
docker-compose -f docker-compose.yml -f docker-compose.prod.yml pull

# コンテナを再作成
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

# 古いイメージを削除
docker image prune -f

ダウンタイムを最小化する更新

ブルーグリーンデプロイメントの簡易版を実現できます。

# 新バージョンを別名で起動
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --scale web=2

# ヘルスチェック確認後、古いコンテナを停止
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --scale web=1

バックアップとロールバック

定期的なバックアップスクリプトを作成します。

#!/bin/bash
# backup.sh
BACKUP_DIR="/backup/$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR

# データベースバックアップ
docker-compose exec -T db pg_dump -U postgres myapp > $BACKUP_DIR/db.sql

# ボリュームバックアップ
docker run --rm -v db-data:/data -v $BACKUP_DIR:/backup alpine tar czf /backup/db-data.tar.gz -C /data .

ロールバック時は、イメージのバージョンを戻して再デプロイします。

# .envのAPP_VERSIONを前バージョンに変更
vi .env

# 再デプロイ
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

監視とトラブルシューティング

基本的な監視コマンド

# コンテナの状態確認
docker-compose ps

# リソース使用状況
docker stats

# ログ確認
docker-compose logs -f web
docker-compose logs --tail=100 db

よくあるトラブルと解決方法

コンテナが起動しない場合:

# 詳細ログを確認
docker-compose logs web

# ヘルスチェック状態を確認
docker inspect --format='{{json .State.Health}}' container_name

メモリ不足の場合:

リソース制限を見直し、不要なコンテナを停止します。

# メモリ使用量の多いコンテナを特定
docker stats --no-stream --format "table {{.Container}}\t{{.MemUsage}}"

ディスク容量不足の場合:

# 未使用リソースを削除
docker system prune -a --volumes

まとめ

Docker Composeは、適切な設定と運用を行えば本番環境でも十分に使えるツールです。特に中小規模のシステムでは、Kubernetesのような複雑なツールより、シンプルで管理しやすいDocker Composeが適しています。

重要なポイント:

  • 開発環境と本番環境の設定を明確に分離する
  • 自動再起動、リソース制限、ログローテーションを必ず設定する
  • 機密情報は環境変数で管理し、Gitにコミットしない
  • イメージのバージョンを固定し、定期的にアップデートする
  • 定期的なバックアップとロールバック手順を準備する

月間数十万PV程度のWebサービスや、数十人が利用する社内システムなら、Docker Composeで十分に安定稼働できます。「完璧なシステム」よりも「現実的に運用できるシステム」を選ぶことが、中小企業には重要です。

まずは小さく始めて、システムの成長に合わせて段階的に改善していきましょう。不明点があれば、Docker公式ドキュメントやコミュニティフォーラムを活用してください。

#Docker#Compose#本番環境
共有:

ちょっとした業務の悩みも、気軽にご相談ください。

まずは話だけ聞いてもらう