🚀 STEP 27: プロジェクト③ 本番環境デプロイシミュレーション
開発環境から本番環境へ – プロダクションレディなシステム構築
📋 このプロジェクトのゴール
- 開発環境と本番環境の設定分離
- Docker Secretsによるシークレット管理
- イメージのタグ管理とバージョニング
- ログ集約とログローテーション
- リソース制限とパフォーマンスチューニング
- バックアップ・リストア手順の確立
- 本番デプロイのチェックリスト作成
目標:本番環境で安定稼働するシステムの構築と運用手順の確立
学習時間の目安: 3時間
🔧 0. このプロジェクトの前提知識
📚 これまでの学習の復習
- Docker Compose:マルチコンテナ構成(STEP 15-18)
- 環境変数:.envファイル管理(STEP 21)
- リソース制限:メモリ、CPU制限(STEP 24)
- ETLパイプライン:STEP 25-26のプロジェクト
- ヘルスチェック:コンテナ監視(STEP 24)
0-1. 作業ディレクトリの準備
mkdir -p ~/docker-practice/step27
cd ~/docker-practice/step27
pwd
0-2. 本番環境のアーキテクチャ
【本番環境デプロイ アーキテクチャ】
┌─────────────────────────────────────────────────────────────────────┐
│ 本番環境システム構成 │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Docker Compose │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ PostgreSQL │◄────────────│ ETL │ │ │
│ │ │ :5432 │ DB接続 │ Pipeline │ │ │
│ │ └─────────────┘ └─────────────┘ │ │
│ │ │ │ │ │
│ │ ↓ ↓ │ │
│ │ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Volume │ │ Logs │ │ │
│ │ │ (永続化) │ │ (ファイル) │ │ │
│ │ └─────────────┘ └─────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ 【セキュリティ】 【運用】 │
│ ├── Docker Secrets ├── 自動再起動(restart: always) │
│ ├── 非rootユーザー ├── ヘルスチェック │
│ └── 読み取り専用マウント ├── ログローテーション │
│ └── バックアップ/リストア │
│ │
└─────────────────────────────────────────────────────────────────────┘
0-3. 開発環境と本番環境の違い
| 項目 | 開発環境 | 本番環境 |
|---|---|---|
| デバッグ | 有効(DEBUG=true) | 無効(DEBUG=false) |
| ログレベル | DEBUG | WARNING |
| リソース制限 | なし | 厳密に設定 |
| 再起動ポリシー | no | always |
| パスワード管理 | .envファイル | Docker Secrets |
| データ永続化 | 任意 | 必須 |
| ログ管理 | 標準出力のみ | ローテーション設定 |
| ボリュームマウント | 読み書き可 | 読み取り専用(:ro) |
0-4. 本番環境の要件
【本番環境の5つの要件】
1. 高可用性 2. セキュリティ 3. 監視
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 自動再起動 │ │ Secrets管理 │ │ ヘルスチェック│
│ ヘルスチェック │ │ 非rootユーザー│ │ ログ集約 │
│ 冗長構成 │ │ 最小権限 │ │ メトリクス │
└──────────────┘ └──────────────┘ └──────────────┘
4. パフォーマンス 5. 運用性
┌──────────────┐ ┌──────────────┐
│ リソース制限 │ │ バックアップ │
│ チューニング │ │ ロールバック │
│ スケーリング │ │ ドキュメント │
└──────────────┘ └──────────────┘
📂 1. プロジェクト構造の作成
# プロジェクトディレクトリ作成
mkdir -p production-deploy
cd production-deploy
# ディレクトリ構成
mkdir -p config/{dev,prod}
mkdir -p scripts
mkdir -p src
mkdir -p data/input
mkdir -p logs
mkdir -p backups
# 構造確認
tree -L 2 . || find . -type d
📁 最終的なディレクトリ構造
production-deploy/
├── docker-compose.dev.yml # 開発環境設定
├── docker-compose.prod.yml # 本番環境設定
├── Dockerfile # マルチステージビルド
├── requirements.txt # Python依存関係
├── init.sql # DB初期化
├── config/
│ ├── dev/
│ │ └── .env.dev # 開発環境変数
│ └── prod/
│ ├── .env.prod # 本番環境変数
│ └── db_password.txt # シークレット(Git管理外)
├── scripts/
│ ├── deploy.sh # デプロイスクリプト
│ ├── backup.sh # バックアップ
│ ├── rollback.sh # ロールバック
│ └── health_check.sh # ヘルスチェック
├── src/ # アプリケーションコード
│ └── …(STEP 26と同じ)
├── data/
│ └── input/
│ └── sales_data.csv
├── logs/ # ログファイル
└── backups/ # バックアップファイル
🔐 2. 環境設定ファイルの作成
2-1. 開発環境の設定
# 開発環境の環境変数
cat > config/dev/.env.dev << ‘EOF’
# 開発環境設定
ENV=development
DEBUG=true
LOG_LEVEL=DEBUG
# データベース
DB_NAME=dev_datawarehouse
DB_USER=dev_user
DB_PASSWORD=dev_password_123
# ETL設定
BATCH_SIZE=100
MAX_RETRIES=1
EOF
echo “✅ 開発環境設定ファイル作成完了”
2-2. 本番環境の設定
# 本番環境の環境変数
cat > config/prod/.env.prod << ‘EOF’
# 本番環境設定
ENV=production
DEBUG=false
LOG_LEVEL=WARNING
VERSION=1.0.0
# データベース
DB_NAME=prod_datawarehouse
DB_USER=prod_user
# パスワードはDocker Secretsで管理
# ETL設定
BATCH_SIZE=5000
MAX_RETRIES=5
EOF
# シークレットファイル(Git管理外)
cat > config/prod/db_password.txt << ‘EOF’
very_secure_production_password_456
EOF
# 権限を制限
chmod 600 config/prod/db_password.txt
echo “✅ 本番環境設定ファイル作成完了”
⚠️ セキュリティ注意
db_password.txtは絶対にGitにコミットしない- 本番パスワードは専用のシークレット管理ツールで管理(HashiCorp Vault等)
- ファイル権限は
600(所有者のみ読み書き可)に設定
# .gitignoreに追加
cat >> .gitignore << ‘EOF’
config/prod/db_password.txt
*.txt
backups/
logs/
EOF
⚙️ 3. 開発環境のDocker Compose
# 開発環境用docker-compose.dev.yml
cat > docker-compose.dev.yml << ‘EOF’
version: ‘3.8’
services:
# ============================================
# PostgreSQL(開発環境)
# ============================================
postgres:
image: postgres:15
container_name: dev-postgres
environment:
POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
ports:
– “5432:5432”
volumes:
– postgres_dev_data:/var/lib/postgresql/data
– ./init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
– dev-network
# 開発環境ではヘルスチェックなし、再起動なし
# ============================================
# ETL(開発環境)
# ============================================
etl:
build:
context: .
dockerfile: Dockerfile
target: development # 開発用ステージを使用
container_name: dev-etl
environment:
ENV: development
DEBUG: “true”
LOG_LEVEL: DEBUG
DB_HOST: postgres
DB_PORT: 5432
DB_NAME: ${DB_NAME}
DB_USER: ${DB_USER}
DB_PASSWORD: ${DB_PASSWORD}
volumes:
– ./src:/app/src # ホットリロード用
– ./data:/data
– ./logs:/logs
networks:
– dev-network
depends_on:
– postgres
# 開発中は待機状態
command: tail -f /dev/null
networks:
dev-network:
driver: bridge
volumes:
postgres_dev_data:
EOF
echo “✅ docker-compose.dev.yml 作成完了”
🏭 4. 本番環境のDocker Compose
# 本番環境用docker-compose.prod.yml
cat > docker-compose.prod.yml << ‘EOF’
version: ‘3.8’
services:
# ============================================
# PostgreSQL(本番環境)
# ============================================
postgres:
image: postgres:15
container_name: prod-postgres
environment:
POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER}
# パスワードはSecretから読み込み
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
– db_password
ports:
– “5432:5432”
volumes:
– postgres_prod_data:/var/lib/postgresql/data
– ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
– ./backups:/backups
networks:
– prod-network
healthcheck:
test: [“CMD-SHELL”, “pg_isready -U ${DB_USER} -d ${DB_NAME}”]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
restart: always
deploy:
resources:
limits:
cpus: ‘2.0’
memory: 2G
reservations:
cpus: ‘1.0’
memory: 1G
logging:
driver: “json-file”
options:
max-size: “10m”
max-file: “3”
# ============================================
# ETL(本番環境)
# ============================================
etl:
build:
context: .
dockerfile: Dockerfile
target: production # 本番用ステージを使用
image: etl-pipeline:${VERSION:-latest}
container_name: prod-etl
environment:
ENV: production
DEBUG: “false”
LOG_LEVEL: ${LOG_LEVEL:-WARNING}
DB_HOST: postgres
DB_PORT: 5432
DB_NAME: ${DB_NAME}
DB_USER: ${DB_USER}
BATCH_SIZE: ${BATCH_SIZE:-5000}
MAX_RETRIES: ${MAX_RETRIES:-5}
secrets:
– db_password
volumes:
– ./data/input:/data/input:ro # 読み取り専用
– ./data/output:/data/output
– ./logs:/logs
networks:
– prod-network
depends_on:
postgres:
condition: service_healthy
restart: always
deploy:
resources:
limits:
cpus: ‘1.5’
memory: 1G
reservations:
cpus: ‘0.5’
memory: 512M
healthcheck:
test: [“CMD”, “python”, “-c”, “from src.config import Config; Config.validate()”]
interval: 60s
timeout: 10s
retries: 3
start_period: 30s
logging:
driver: “json-file”
options:
max-size: “50m”
max-file: “5”
# ============================================
# Secrets(Docker Secrets)
# ============================================
secrets:
db_password:
file: ./config/prod/db_password.txt
# ============================================
# Networks
# ============================================
networks:
prod-network:
driver: bridge
# ============================================
# Volumes
# ============================================
volumes:
postgres_prod_data:
EOF
echo “✅ docker-compose.prod.yml 作成完了”
🔐 本番環境の重要な設定
- Docker Secrets:
POSTGRES_PASSWORD_FILEでファイルからパスワードを読み込み - restart: always:異常終了時やDocker再起動時に自動再起動
- ヘルスチェック:30秒間隔でPostgreSQLとETLの健全性を監視
- リソース制限:CPU・メモリの上限と予約を設定
- ログローテーション:
max-sizeとmax-fileでディスク容量を保護 - 読み取り専用:入力データは
:roでセキュリティ向上
🐳 5. マルチステージDockerfile
# マルチステージDockerfile
cat > Dockerfile << ‘EOF’
# ============================================
# ベースイメージ
# ============================================
FROM python:3.11-slim as base
LABEL maintainer=”dataeng” \
version=”1.0″ \
description=”ETL Pipeline Container”
WORKDIR /app
# 非rootユーザー作成
RUN useradd -m -u 1000 -s /bin/bash etluser
# ============================================
# 開発環境ステージ
# ============================================
FROM base as development
# 依存関係インストール
COPY requirements.txt .
RUN pip install –no-cache-dir -r requirements.txt
# アプリケーションコード(開発時はボリュームマウントで上書き)
COPY –chown=etluser:etluser src/ ./src/
# 必要なディレクトリ作成
RUN mkdir -p /data/input /data/output /logs && \
chown -R etluser:etluser /data /logs /app
USER etluser
ENV PYTHONUNBUFFERED=1 \
PYTHONPATH=/app
# 開発時は待機
CMD [“tail”, “-f”, “/dev/null”]
# ============================================
# ビルドステージ(本番用)
# ============================================
FROM base as builder
COPY requirements.txt .
RUN pip install –no-cache-dir –user -r requirements.txt
# ============================================
# 本番環境ステージ
# ============================================
FROM base as production
# Pythonパッケージをビルダーからコピー
COPY –from=builder /root/.local /home/etluser/.local
# アプリケーションコードをコピー
COPY –chown=etluser:etluser src/ ./src/
# 必要なディレクトリ作成
RUN mkdir -p /data/input /data/output /logs && \
chown -R etluser:etluser /data /logs /app
# 非rootユーザーに切り替え
USER etluser
# 環境変数
ENV PATH=/home/etluser/.local/bin:$PATH \
PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONPATH=/app
# ヘルスチェック
HEALTHCHECK –interval=30s –timeout=10s –start-period=5s –retries=3 \
CMD python -c “from src.config import Config; Config.validate()” || exit 1
# デフォルトコマンド
CMD [“python”, “-m”, “src.etl”, “sales_data.csv”]
EOF
echo “✅ Dockerfile 作成完了”
📜 6. デプロイ・運用スクリプト
6-1. デプロイスクリプト
# scripts/deploy.sh
cat > scripts/deploy.sh << ‘EOF’
#!/bin/bash
set -e
echo “🚀 ======================================”
echo “🚀 本番環境デプロイ開始”
echo “🚀 ======================================”
# 環境変数読み込み
export $(cat config/prod/.env.prod | grep -v ‘^#’ | xargs)
# バージョン確認
echo “”
echo “📦 デプロイバージョン: ${VERSION}”
echo “📅 日時: $(date ‘+%Y-%m-%d %H:%M:%S’)”
echo “”
read -p “このバージョンでデプロイしますか? (y/n): ” -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo “❌ デプロイをキャンセルしました”
exit 1
fi
# イメージビルド
echo “”
echo “🔨 Dockerイメージをビルド中…”
docker build \
–target production \
–tag etl-pipeline:${VERSION} \
–tag etl-pipeline:latest \
.
# 既存のバックアップ作成
echo “”
echo “💾 データベースのバックアップ作成中…”
if docker ps | grep -q prod-postgres; then
./scripts/backup.sh
else
echo ” ⚠️ PostgreSQLコンテナが起動していないためスキップ”
fi
# 古いコンテナを停止
echo “”
echo “⏸️ 既存のコンテナを停止中…”
docker-compose -f docker-compose.prod.yml –env-file config/prod/.env.prod down 2>/dev/null || true
# 新しいコンテナを起動
echo “”
echo “▶️ 新しいコンテナを起動中…”
docker-compose -f docker-compose.prod.yml –env-file config/prod/.env.prod up -d
# ヘルスチェック待機
echo “”
echo “⏳ コンテナの起動を待機中(30秒)…”
sleep 30
# ヘルスチェック
echo “”
echo “🏥 ヘルスチェック実行中…”
./scripts/health_check.sh
if [ $? -eq 0 ]; then
echo “”
echo “✅ ======================================”
echo “✅ デプロイ完了!”
echo “✅ ======================================”
echo “”
echo “📊 ログ確認コマンド:”
echo ” docker-compose -f docker-compose.prod.yml logs -f”
else
echo “”
echo “❌ ======================================”
echo “❌ デプロイ失敗”
echo “❌ ======================================”
echo “”
echo “🔙 ロールバックを実行してください:”
echo ” ./scripts/rollback.sh”
exit 1
fi
EOF
chmod +x scripts/deploy.sh
echo “✅ deploy.sh 作成完了”
6-2. バックアップスクリプト
# scripts/backup.sh
cat > scripts/backup.sh << ‘EOF’
#!/bin/bash
set -e
BACKUP_DIR=”./backups”
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE=”backup_${TIMESTAMP}.dump”
# 環境変数読み込み
export $(cat config/prod/.env.prod | grep -v ‘^#’ | xargs)
mkdir -p ${BACKUP_DIR}
echo “💾 データベースバックアップ開始…”
echo ” 対象: ${DB_NAME}”
echo ” ファイル: ${BACKUP_DIR}/${BACKUP_FILE}”
# pg_dumpでバックアップ(カスタム形式)
docker exec prod-postgres pg_dump \
-U ${DB_USER} \
-d ${DB_NAME} \
-F c \
-f /backups/${BACKUP_FILE}
# バックアップファイルのサイズ確認
BACKUP_SIZE=$(ls -lh ${BACKUP_DIR}/${BACKUP_FILE} | awk ‘{print $5}’)
echo “✅ バックアップ完了: ${BACKUP_FILE} (${BACKUP_SIZE})”
# 古いバックアップを削除(7日以上前)
OLD_COUNT=$(find ${BACKUP_DIR} -name “backup_*.dump” -mtime +7 | wc -l)
if [ $OLD_COUNT -gt 0 ]; then
find ${BACKUP_DIR} -name “backup_*.dump” -mtime +7 -delete
echo “🗑️ 古いバックアップを ${OLD_COUNT} 件削除しました”
fi
# バックアップ一覧
echo “”
echo “📁 現在のバックアップ一覧:”
ls -lh ${BACKUP_DIR}/backup_*.dump 2>/dev/null || echo ” バックアップなし”
EOF
chmod +x scripts/backup.sh
echo “✅ backup.sh 作成完了”
6-3. ロールバックスクリプト
# scripts/rollback.sh
cat > scripts/rollback.sh << ‘EOF’
#!/bin/bash
set -e
echo “🔙 ======================================”
echo “🔙 ロールバック開始”
echo “🔙 ======================================”
# 環境変数読み込み
export $(cat config/prod/.env.prod | grep -v ‘^#’ | xargs)
# 最新のバックアップを確認
LATEST_BACKUP=$(ls -t backups/backup_*.dump 2>/dev/null | head -1)
if [ -z “$LATEST_BACKUP” ]; then
echo “❌ バックアップファイルが見つかりません”
exit 1
fi
echo “”
echo “📦 利用可能なバックアップ:”
ls -lh backups/backup_*.dump
echo “”
echo “📦 選択されたバックアップ: ${LATEST_BACKUP}”
echo “”
read -p “このバックアップでロールバックしますか? (y/n): ” -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo “❌ ロールバックをキャンセルしました”
exit 1
fi
# PostgreSQLのみ起動
echo “”
echo “⏸️ ETLコンテナを停止中…”
docker-compose -f docker-compose.prod.yml –env-file config/prod/.env.prod stop etl
echo “”
echo “🔄 データベースをリストア中…”
# リストア実行
BACKUP_FILENAME=$(basename ${LATEST_BACKUP})
docker exec prod-postgres pg_restore \
-U ${DB_USER} \
-d ${DB_NAME} \
-c \
/backups/${BACKUP_FILENAME} || true
# ETLコンテナを再起動
echo “”
echo “▶️ ETLコンテナを再起動中…”
docker-compose -f docker-compose.prod.yml –env-file config/prod/.env.prod start etl
echo “”
echo “✅ ======================================”
echo “✅ ロールバック完了”
echo “✅ ======================================”
EOF
chmod +x scripts/rollback.sh
echo “✅ rollback.sh 作成完了”
6-4. ヘルスチェックスクリプト
# scripts/health_check.sh
cat > scripts/health_check.sh << ‘EOF’
#!/bin/bash
echo “🏥 ヘルスチェック開始…”
echo “”
EXIT_CODE=0
# 環境変数読み込み
export $(cat config/prod/.env.prod | grep -v ‘^#’ | xargs)
# 1. PostgreSQLチェック
echo “📊 [1/4] PostgreSQL…”
if docker exec prod-postgres pg_isready -U ${DB_USER} -d ${DB_NAME} > /dev/null 2>&1; then
echo ” ✅ PostgreSQL: 正常”
else
echo ” ❌ PostgreSQL: 異常”
EXIT_CODE=1
fi
# 2. ETLコンテナチェック
echo “🔄 [2/4] ETLコンテナ…”
CONTAINER_STATUS=$(docker inspect -f ‘{{.State.Status}}’ prod-etl 2>/dev/null || echo “not found”)
if [ “$CONTAINER_STATUS” = “running” ]; then
echo ” ✅ ETLコンテナ: 実行中”
else
echo ” ❌ ETLコンテナ: ${CONTAINER_STATUS}”
EXIT_CODE=1
fi
# 3. ディスク容量チェック
echo “💾 [3/4] ディスク容量…”
DISK_USAGE=$(df -h / | awk ‘NR==2 {print $5}’ | sed ‘s/%//’)
if [ $DISK_USAGE -lt 80 ]; then
echo ” ✅ ディスク使用率: ${DISK_USAGE}% (正常)”
elif [ $DISK_USAGE -lt 90 ]; then
echo ” ⚠️ ディスク使用率: ${DISK_USAGE}% (警告)”
else
echo ” ❌ ディスク使用率: ${DISK_USAGE}% (危険)”
EXIT_CODE=1
fi
# 4. メモリ使用量チェック
echo “🧠 [4/4] メモリ使用量…”
MEMORY_USAGE=$(docker stats –no-stream –format “{{.MemPerc}}” prod-postgres prod-etl 2>/dev/null | head -1 | sed ‘s/%//’)
if [ -n “$MEMORY_USAGE” ]; then
echo ” ✅ コンテナメモリ: 確認済み”
else
echo ” ⚠️ メモリ使用量: 取得できません”
fi
echo “”
if [ $EXIT_CODE -eq 0 ]; then
echo “✅ すべてのヘルスチェック完了”
else
echo “❌ ヘルスチェックに失敗した項目があります”
fi
exit $EXIT_CODE
EOF
chmod +x scripts/health_check.sh
echo “✅ health_check.sh 作成完了”
✅ 7. デプロイチェックリスト
📋 デプロイ前チェックリスト
- 環境変数ファイル(.env.prod)の値を確認
- シークレットファイル(db_password.txt)が存在する
- Dockerイメージのビルドが成功する
- 最新のデータベースバックアップを取得済み
- リソース制限の設定値が適切
- ヘルスチェックの設定が正しい
- ログローテーション設定を確認
- ネットワーク設定を確認
- バージョン番号を更新した
- ロールバック手順を確認した
📋 デプロイ後チェックリスト
- すべてのコンテナが起動している
- ヘルスチェックスクリプトが成功
- ログが正常に出力されている
- データベース接続が成功
- ETL処理が正常に実行される
- リソース使用率が正常範囲内
- ディスク容量に余裕がある(80%未満)
- エラーログがない
🚀 8. デプロイ実行手順
8-1. 開発環境でテスト
# 開発環境で動作確認
docker-compose -f docker-compose.dev.yml \
–env-file config/dev/.env.dev up -d
# コンテナ状態確認
docker-compose -f docker-compose.dev.yml ps
# 手動でETL実行テスト
docker-compose -f docker-compose.dev.yml exec etl \
python -m src.etl sales_data.csv
# 問題なければ停止
docker-compose -f docker-compose.dev.yml down
8-2. 本番デプロイ実行
# デプロイスクリプトを実行
./scripts/deploy.sh
🚀 ======================================
🚀 本番環境デプロイ開始
🚀 ======================================
📦 デプロイバージョン: 1.0.0
📅 日時: 2024-01-20 10:30:00
このバージョンでデプロイしますか? (y/n): y
🔨 Dockerイメージをビルド中…
[+] Building 15.2s (12/12) FINISHED
=> => naming to docker.io/library/etl-pipeline:1.0.0
💾 データベースのバックアップ作成中…
✅ バックアップ完了: backup_20240120_103015.dump (256K)
⏸️ 既存のコンテナを停止中…
▶️ 新しいコンテナを起動中…
⏳ コンテナの起動を待機中(30秒)…
🏥 ヘルスチェック実行中…
📊 [1/4] PostgreSQL…
✅ PostgreSQL: 正常
🔄 [2/4] ETLコンテナ…
✅ ETLコンテナ: 実行中
💾 [3/4] ディスク容量…
✅ ディスク使用率: 45% (正常)
🧠 [4/4] メモリ使用量…
✅ コンテナメモリ: 確認済み
✅ すべてのヘルスチェック完了
✅ ======================================
✅ デプロイ完了!
✅ ======================================
8-3. 動作確認
# コンテナ状態確認
docker-compose -f docker-compose.prod.yml ps
# リソース使用状況
docker stats –no-stream prod-postgres prod-etl
# ログ確認
docker-compose -f docker-compose.prod.yml logs –tail 50
# データベース確認
docker exec prod-postgres psql -U prod_user -d prod_datawarehouse \
-c “SELECT COUNT(*) FROM sales;”
🔄 9. 運用タスク
9-1. 定期バックアップ(Cron設定)
# crontabを編集
crontab -e
# 毎日午前2時にバックアップ
0 2 * * * cd /path/to/production-deploy && ./scripts/backup.sh >> logs/backup.log 2>&1
# 毎時ヘルスチェック
0 * * * * cd /path/to/production-deploy && ./scripts/health_check.sh >> logs/health.log 2>&1
9-2. ログの確認
# リアルタイムログ
docker-compose -f docker-compose.prod.yml logs -f
# 特定のサービスのみ
docker-compose -f docker-compose.prod.yml logs -f etl
# 最新100行(タイムスタンプ付き)
docker-compose -f docker-compose.prod.yml logs –tail 100 -t
# エラーログのみ抽出
docker-compose -f docker-compose.prod.yml logs 2>&1 | grep -i error
9-3. ディスク容量管理
# ディスク使用状況
df -h
# Dockerのディスク使用状況
docker system df
# 未使用リソースのクリーンアップ(注意して実行)
docker system prune -a –volumes
# 古いイメージのみ削除
docker image prune -a –filter “until=168h” # 7日以上前
9-4. コンテナの再起動
# 特定のサービスを再起動
docker-compose -f docker-compose.prod.yml –env-file config/prod/.env.prod restart etl
# すべてのサービスを再起動
docker-compose -f docker-compose.prod.yml –env-file config/prod/.env.prod restart
# 設定変更後の再起動(コンテナ再作成)
docker-compose -f docker-compose.prod.yml –env-file config/prod/.env.prod up -d –force-recreate
💪 10. 練習問題
練習問題 1
基礎
開発環境と本番環境で異なる設定を3つ挙げて、その理由を説明してください。
- ログレベル(DEBUG→WARNING):本番では不要な詳細ログを抑制してパフォーマンス向上とディスク節約
- 再起動ポリシー(no→always):本番では障害時に自動復旧して可用性を確保
- パスワード管理(.env→Secrets):本番ではより安全な方法で機密情報を管理
練習問題 2
基礎
Docker Secretsを使う利点は何ですか?
- 環境変数より安全:環境変数は
docker inspectで見えてしまうが、Secretsはメモリ上のみで管理 - ファイルシステム経由:
/run/secrets/にマウントされ、コンテナ内からファイルとして読み取り - 暗号化保存:Swarm Modeでは暗号化されて保存される
- アクセス制限:必要なコンテナのみがSecretにアクセス可能
練習問題 3
応用
ログローテーションの設定(max-size: 50m, max-file: 5)の意味と、この設定で使用される最大ディスク容量を計算してください。
設定の意味:
max-size: 50m: 1つのログファイルの最大サイズは50MBmax-file: 5: 保持するログファイルの最大数は5個
最大ディスク容量:
50MB × 5ファイル = 250MB(1コンテナあたり)
PostgreSQL + ETL = 250MB × 2 = 500MB(システム全体)
練習問題 4
応用
バックアップスクリプトを週次バックアップ(毎週日曜午前3時)に変更するCron設定を書いてください。
# 毎週日曜日の午前3時に実行
0 3 * * 0 cd /path/to/production-deploy && ./scripts/backup.sh >> logs/backup.log 2>&1
# Cron形式の説明
# ┌───────────── 分 (0-59)
# │ ┌─────────── 時 (0-23)
# │ │ ┌───────── 日 (1-31)
# │ │ │ ┌─────── 月 (1-12)
# │ │ │ │ ┌───── 曜日 (0-6, 0=日曜)
# │ │ │ │ │
# 0 3 * * 0
練習問題 5
発展
ゼロダウンタイムデプロイ(無停止デプロイ)を実現するための方法を2つ説明してください。
方法1: ブルー・グリーンデプロイメント
- 現在稼働中の環境(ブルー)とは別に、新バージョンの環境(グリーン)を構築
- グリーン環境でテスト完了後、ロードバランサーで切り替え
- 問題発生時は即座にブルーに戻せる
方法2: ローリングアップデート(Kubernetes/Docker Swarm)
- 複数のレプリカを順番に新バージョンに更新
- 常に一部のコンテナが稼働中
docker service update --update-parallelism 1で制御
📝 STEP 27 のまとめ
✅ このプロジェクトで習得したスキル
- 環境分離:開発環境と本番環境の設定を完全に分離
- シークレット管理:Docker Secretsによる安全なパスワード管理
- マルチステージビルド:開発用・本番用のステージを1つのDockerfileで管理
- リソース制限:CPU・メモリの制限と予約の設定
- ログ管理:ログローテーションによるディスク容量保護
- 運用自動化:デプロイ、バックアップ、ヘルスチェックのスクリプト化
- チェックリスト:デプロイ前後の確認項目の整理
📊 本番環境運用の重要ポイント
| カテゴリ | ポイント | 実装方法 |
|---|---|---|
| 自動化 | 人的ミスを防止 | deploy.sh, backup.sh |
| 監視 | 異常の早期発見 | health_check.sh, ヘルスチェック |
| バックアップ | データ損失防止 | pg_dump, Cron設定 |
| セキュリティ | 機密情報保護 | Docker Secrets, 非rootユーザー |
| 可用性 | サービス継続 | restart: always, ヘルスチェック |
🎉 コース完了おめでとうございます!
✨ このコースで学んだこと
- Part 1-2(STEP 1-10):Dockerの基礎とイメージ管理
- Part 3(STEP 11-14):Dockerfileの作成と最適化
- Part 4(STEP 15-18):Docker Composeとネットワーキング
- Part 5(STEP 19-24):データエンジニアリング実践
- Part 6(STEP 25-27):総合演習と本番デプロイ
🚀 次のステップ
- Kubernetes:より大規模なシステムのオーケストレーション
- CI/CD深掘り:GitHub Actions、GitLab CI、ArgoCD
- クラウド:AWS ECS/EKS、Google Cloud Run/GKE、Azure AKS
- モニタリング:Prometheus、Grafana、Datadog
- セキュリティ:Trivy、Falco、OPA
💼 実務での活用
このコースで学んだスキルは、データエンジニアとして即座に実務で活用できます。
- ETLパイプラインのコンテナ化と運用
- PostgreSQL、Airflow、Sparkの環境構築
- 開発環境の標準化とチーム共有
- CI/CDパイプラインの構築
- 本番環境へのデプロイと運用
🎓 コース完了
全27ステップをクリアしました!
あなたはDockerとコンテナ技術を実務レベルで扱えるデータエンジニアです。
学習メモ
Docker・コンテナ技術入門 - Step 27
📋 過去のメモ一覧
▼