Dockerコンテナの高度な運用:モニタリング・チューニング・障害対応実践ガイド

7.1 リアルタイム可視化とログ集約

本節では、コンテナの挙動を可視化し、ログを効率的に集約するための実践的な手法を解説します。

7.1.1 モニタリングの基礎知識

  • メトリクス取得:CPU、メモリ、ネットワークI/O、ディスクI/Oを継続的に収集し、閾値超過を検知します。
  • ログパイプライン:Fluent Bit → Elasticsearch → Kibana のようなパイプラインを構築し、構造化ログを一元管理します。
  • アラート設計:Prometheus Alertmanager を用いて、SLA違反やエラーレート上昇を自動通知します。
  • セキュアなログ転送:mTLS で保護した Fluentd Aggregator を経由し、GDPR/PIPA 要件を満たします。

7.1.2 実践:FlaskアプリをPrometheus+Grafanaで監視

以下の手順で、Flaskアプリのメトリクスを取得し、Grafanaダッシュボードで可視化します。

  1. アプリケーション実装
    # main.py
    from flask import Flask
    from prometheus_client import Counter, Histogram, generate_latest
    import time
    
    app = Flask(__name__)
    req_count = Counter('flask_requests_total', 'Total requests', ['method', 'endpoint'])
    req_latency = Histogram('flask_request_duration_seconds', 'Latency', ['method', 'endpoint'])
    
    @app.route('/')
    def index():
        start = time.time()
        req_count.labels(method='GET', endpoint='/').inc()
        time.sleep(0.1)
        req_latency.labels(method='GET', endpoint='/').observe(time.time() - start)
        return "OK"
    
    @app.route('/metrics')
    def metrics():
        return generate_latest()
    
  2. Dockerfile
    FROM python:3.11-slim
    WORKDIR /srv
    COPY requirements.txt .
    RUN pip install -r requirements.txt
    COPY main.py .
    CMD ["gunicorn", "-b", "0.0.0.0:5000", "main:app"]
    
  3. Prometheus設定
    # prometheus.yml
    global:
      scrape_interval: 10s
    scrape_configs:
      - job_name: flask
        static_configs:
          - targets: ['flask:5000']
    
  4. Compose起動
    # compose.yml
    services:
      flask:
        build: .
        ports: ["5000:5000"]
      prometheus:
        image: prom/prometheus
        ports: ["9090:9090"]
        volumes: ["./prometheus.yml:/etc/prometheus/prometheus.yml"]
      grafana:
        image: grafana/grafana
        ports: ["3000:3000"]
        environment:
          - GF_SECURITY_ADMIN_PASSWORD=admin
    

7.1.3 応用:ELKスタックで構造化ログを分析

Filebeat → Logstash → Elasticsearch → Kibana のパイプラインを Docker Compose で起動し、JSONログをダッシュボード化します。

# elk-compose.yml
version: "3.9"
services:
  filebeat:
    image: docker.elastic.co/beats/filebeat:8.12.0
    user: root
    volumes:
      - /var/lib/docker/containers:/var/lib/docker/containers:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./filebeat.yml:/usr/share/filebeat/filebeat.yml
  logstash:
    image: docker.elastic.co/logstash/logstash:8.12.0
    volumes: ["./logstash.conf:/usr/share/logstash/pipeline/logstash.conf"]
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
    ports: ["9200:9200"]
  kibana:
    image: docker.elastic.co/kibana/kibana:8.12.0
    ports: ["5601:5601"]

7.2 リソース制限とパフォーマンス最適化

7.2.1 リソース制御の基礎

  • CPU制限:--cpus 2.0 --cpuset-cpus 0-1 で2コア限定。
  • メモリ制限:--memory 512m --memory-swap 1g でスワップも含めて制御。
  • I/O帯域:--device-read-bps /dev/sda:10mb でディスク帯域を抑止。
  • ネットワーク:macvlan や ipvlan を使い、ホストと同レベルのスループットを実現。

7.2.2 実践:Flaskアプリのリソース最適化

  1. マルチステージビルドで軽量化
    # Dockerfile
    FROM python:3.11-alpine AS builder
    WORKDIR /build
    COPY requirements.txt .
    RUN pip install --user -r requirements.txt
    
    FROM python:3.11-alpine
    WORKDIR /app
    COPY --from=builder /root/.local /usr/local
    COPY app.py .
    EXPOSE 5000
    CMD ["python", "app.py"]
    
  2. cgroups v2で厳密制限
    docker run -d \
      --name flask-restricted \
      --cpus="0.5" \
      --memory="256m" \
      --pids-limit 100 \
      flask-optimized
    
  3. ベンチマーク
    wrk -t4 -c100 -d30s http://localhost:5000/
    

7.2.3 ネットワーク最適化:hostモード活用

# hostモードでレイテンシ削減
docker run -d --network host flask-optimized

# ベンチマーク比較
ab -n 10000 -c 100 http://127.0.0.1:5000/

7.2.4 ストレージ最適化:高速ボリュームマウント

# NVMe SSDを直接マウント
docker run -d \
  --name flask-io \
  --mount type=bind,source=/mnt/nvme0n1,target=/data \
  --storage-opt size=10G \
  flask-optimized

7.3 トラブルシューティングとリカバリー

7.3.1 基本手順

  1. ステータス確認:docker ps -a で Exit コードを確認。
  2. ログ確認:docker logs --tail 100 -f <container>
  3. イベントストリーム:code>docker events --filter event=die
  4. インスペクト:docker inspect --format='{{.State.Error}}' <container>
  5. デバッグコンテナ:docker run --rm -it --pid=container:<target> nicolaka/netshoot /bin/bash

7.3.2 実践:Flaskアプリの異常終了を調査

# 1. 異常終了を再現
docker run -d --name flask-crash flask-buggy

# 2. ログ確認
docker logs flask-crash

# 3. 設定確認
docker inspect flask-crash | jq '.[0].Config.Env'

# 4. コンテナ内へアタッチ
docker exec -it flask-crash sh

7.3.3 ネットワーク接続障害の診断

# 1. ネットワーク一覧
docker network ls

# 2. 接続テスト
docker run --rm -it --network mynet nicolaka/netshoot \
  curl http://db:3306

# 3. DNS解決確認
docker run --rm -it --network mynet nicolaka/netshoot \
  nslookup db

7.3.4 ボリューム権限エラーの解消

# 1. UID/GID確認
docker run --rm -v $(pwd)/uploads:/data alpine id

# 2. 権限修正
docker run --rm -v $(pwd)/uploads:/data alpine \
  sh -c "chown -R 1000:1000 /data"

# 3. 再実行
docker run -d -v $(pwd)/uploads:/data flask-uploader

7.3.5 自動リカバリー設定

# compose.yml
services:
  flask:
    build: .
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

タグ: Docker monitoring Prometheus grafana ELK-Stack

6月4日 23:32 投稿