Docker: パフォーマンスチューニングとトラブルシューティング

最終更新:2026-08-26

本番環境のコンテナで問題が発生していませんか——CPU 使用率が高い、メモリがオーバーロードする、I/O が遅い。こうした状況には体系的なトラブルシューティングアプローチが必要です。

1. 学べること



2. 早朝のアラートの物語

(1) 悩み: API レイテンシが 50 ms から 5 s へ急増

本番環境の API レイテンシが 50 ms から 5 s へ急増し、ユーザーからの苦情が殺到しました。Alice は docker stats で原因を調べたところ、CPU 使用率はスパイクしていないものの、I/O 待機時間が極めて高く、コンテナが「固まっている」ように見えました。

(2) 体系的なトラブルシューティング

Alice は iostat を使ってログドライバがディスク I/O を限界まで使い切っていることを突き止め、ログドライバを切り替えて問題を解消しました。

BASH
# ステップ 1: リソース使用量を確認
docker stats --no-stream

# ステップ 2: ホストの I/O を確認
iostat -x 1 5

# ステップ 3: ボトルネックを特定
docker system df -v

(3) 効果: 5 秒 → 50 ミリ秒、復旧時間わずか 10 分

アラート発生から解決までわずか 10 分。「再起動してみる」という場当たり的な対応よりも、体系的なトラブルシューティングのほうが 100 倍効率的です。



3. パフォーマンストラブルシューティングの意思決定ツリー

(1) 4 つの主要なボトルネックと対応するツール

100%
graph TB
    START["パフォーマンス問題"] --> CPU{"CPU が高い?"}
    CPU -->|はい| C1["docker stats<br/>top / htop"]
    CPU -->|いいえ| MEM{"メモリ使用量が高い?"}
    MEM -->|はい| M1["docker stats<br/>/proc/meminfo"]
    MEM -->|いいえ| IO{"I/O 待機が高い?"}
    IO -->|はい| I1["iostat -x<br/>docker system df"]
    IO -->|いいえ| NET{"ネットワークが遅い?"}
    NET -->|はい| N1["iperf / ping<br/>tcpdump"]

(2) 一般的なトラブルシューティングツール

ツール 機能 用途
docker stats コンテナのリソース使用量 CPU / メモリ / I/O の概要
docker system df Docker のディスク使用量 ディスクフルの調査
docker events コンテナイベントストリーム OOM / 再起動 / 異常終了
docker logs コンテナログ アプリケーションエラー
docker inspect コンテナ設定 ステータス / 終了コード / ネットワーク
iostat ディスク I/O 統計 I/O ボトルネック
iperf ネットワーク帯域テスト ネットワークボトルネック
nsenter コンテナ名前空間への進入 高度なデバッグ


4. CPU ボトルネックのトラブルシューティング

▶ サンプル: docker stats でリソースを監視 (難易度: ⭐)

BASH
# 全コンテナをリアルタイムで監視
docker stats

# ワンショットスナップショット
docker stats --no-stream

# カスタムフォーマット
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}"

▶ サンプル: stress コンテナで CPU 負荷をシミュレート (難易度: ⭐⭐)

BASH
# stress を実行して CPU 負荷をシミュレート
docker run --rm --name stress-test \
  --cpus=1 \
  progrium/stress --cpu 1 --timeout 30s

# 別のターミナルで docker stats を使って監視
docker stats stress-test --no-stream


5. メモリボトルネックのトラブルシューティング

(1) よくあるメモリ問題

症状 終了コード 原因 対策
OOM Kill 137 --memory 上限を超過 上限を引き上げる、またはメモリ使用量を最適化
メモリリーク 徐々に増加 アプリケーションのバグ ヒープダンプの解析
キャッシュ使用量が高い 0 ファイルシステムキャッシュ 正常な動作 (回収可能)

▶ サンプル: コンテナ OOM のシミュレーション (難易度: ⭐⭐⭐)

BASH
# 50 MB のメモリ制限でコンテナを起動
docker run -d --name oom-test \
  --memory=50m \
  --restart=on-failure:3 \
  progrium/stress --vm 1 --vm-bytes 100M --timeout 10s

# OOM イベントを監視
docker events --filter event=oom --since 1m

# 終了コードを確認
docker inspect oom-test --format='ExitCode: {{.State.ExitCode}}, OOMKilled: {{.State.OOMKilled}}'


6. ディスク I/O ボトルネックのトラブルシューティング

▶ サンプル: docker system df でディスクを分析 (難易度: ⭐⭐)

BASH
# Docker のディスク使用量を表示
docker system df

# 詳細な内訳
docker system df -v
💻 出力:

TEXT 📖 参照専用
TYPE            TOTAL   ACTIVE  SIZE      RECLAIMABLE
Images          12      5       4.2GB     2.8GB (66%)
Containers      8       3       350MB     280MB (80%)
Local Volumes   5       3       1.2GB     500MB (41%)
Build Cache     45      0       800MB     800MB (100%)

▶ サンプル: ディスククリーンアップポリシー (難易度: ⭐⭐)

BASH
# 未使用のデータ (イメージ、コンテナ、ボリューム、ビルドキャッシュ) を削除
docker system prune

# より積極的: 未使用のイメージをすべて削除 (dangling だけでなく)
docker system prune -a

# ビルドキャッシュのみを削除
docker builder prune

# ボリュームを削除 (注意: データが削除されます)
docker volume prune

(1) ストレージドライバの比較

ドライバ パフォーマンス 安定性 推奨
overlay2 ✅ 安定 ✅ デフォルトで推奨
aufs ⚠️ 古いカーネル ❌ 非推奨
devicemapper ⚠️ 設定が複雑 ❌ 非推奨
zfs ✅ 安定 特定のシナリオ
btrfs ⚠️ 不安定 ❌ 非推奨


7. ネットワークトラブルシューティング

▶ サンプル: iperf によるネットワーク帯域テスト (難易度: ⭐⭐⭐)

BASH
# コンテナ内で iperf3 サーバーを起動
docker run -d --name iperf-server --network host networkstatic/iperf3 -s

# 別のコンテナから iperf3 クライアントを実行
docker run --rm --network host networkstatic/iperf3 -c localhost -t 10

# 異なるネットワーク上の 2 つのコンテナ間でテスト
docker run --rm --network app-net networkstatic/iperf3 -c db -t 5

▶ サンプル: Docker Events によるイベントトレース (難易度: ⭐⭐)

BASH
# コンテナライフサイクルイベントを監視
docker events --filter type=container

# 特定のイベントでフィルタ
docker events --filter event=oom --filter event=die --filter event=restart

# 時刻ベースのフィルタ
docker events --since "2024-01-15T03:00:00" --until "2024-01-15T04:00:00"


8. 高度なデバッグ: nsenter

▶ サンプル: nsenter でコンテナ名前空間に進入 (難易度: ⭐⭐⭐)

BASH
# コンテナのメイン PID を取得
PID=$(docker inspect --format='{{.State.Pid}}' myapp)

# コンテナのネットワーク名前空間に進入してデバッグ
nsenter -t $PID -n tcpdump -i eth0 -c 100 port 8080

# コンテナのプロセス名前空間に進入
nsenter -t $PID -p -m strace -p 1
💡 ヒント: nsenter は docker exec より低いレベルで動作し、コンテナ内にシェルが不要で、コンテナの Linux 名前空間に直接進入します。scratch イメージや distroless イメージのデバッグに適しています。**



9. トラブルシューティングガイド: よくある問題と解決策

症状 トラブルシューティングコマンド よくある原因 解決策
コンテナが頻繁に再起動する docker ps -a + docker logs OOM / アプリクラッシュ メモリ増設 / バグ修正 / 再起動ポリシー
ディスクスペースが満杯 docker system df -v ログ / イメージ / ボリュームの蓄積 docker system prune + ログローテーション
ネットワーク接続がタイムアウト docker exec ping + nc ネットワーク設定エラー ネットワーク / DNS / ポートを確認
ビルドが遅い docker build --progress=plain キャッシュの期限切れ COPY の順序を調整
コンテナ起動に失敗 docker logs + docker inspect 設定エラー / 依存関係の不足 設定を修正 / 依存関係を確認
I/O 待機が高い iostat -x ログドライバ / 大量書き込み ログドライバを切り替え / 書き込みを最適化


10. 完全なサンプル: コンテナ OOM 問題のトラブルシューティングと解決

BASH
# ============================================
# 完全な手順: OOM 診断と修正
# カバー範囲: stats、events、logs、inspect、修正
# ============================================

# 1. 問題のあるコンテナをデプロイ
docker run -d \
  --name leaky-app \
  --memory=100m \
  --restart=on-failure:5 \
  -p 8080:8080 \
  myapp:1.0

# 2. リソース使用量を監視
docker stats leaky-app --no-stream

# 3. メモリリークをシミュレート (OOM を発生させる)
docker exec leaky-app python -c "
import itertools
data = []
for i in itertools.count():
    data.append('x' * 1024 * 1024)  # 1 MB ずつ
    if i % 10 == 0:
        import time; time.sleep(0.1)
"

# 4. OOM イベントをキャプチャ
docker events --filter container=leaky-app --filter event=oom --since 1m

# 5. 終了コードと OOM ステータスを確認
docker inspect leaky-app --format='
ExitCode: {{.State.ExitCode}}
OOMKilled: {{.State.OOMKilled}}
Memory Limit: {{.HostConfig.Memory}}
'

# 6. アプリログでメモリパターンを確認
docker logs --tail 100 leaky-app 2>&1 | grep -i "memory\|alloc\|oom"

# 7. 対策: メモリ上限を引き上げる
docker stop leaky-app && docker rm leaky-app
docker run -d \
  --name leaky-app \
  --memory=512m \
  --restart=on-failure:5 \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  -p 8080:8080 \
  myapp:1.0

# 8. 監視アラートを設定
docker events --filter event=oom | while read event; do
  echo "ALERT: OOM detected at $(date)" >> /var/log/docker-alerts.log
done

❓ よくある質問

Q コンテナのパフォーマンス問題を階層的にトラブルシューティングするにはどうすればよいですか?
A 4 ステップのアプローチです。① docker stats で CPU、メモリ、I/O の概要を確認。② 最も高い指標に応じて適切なツールを選択 (CPU → top、メモリ → smem、I/O → iostat、ネットワーク → iperf)。③ 具体的なコンテナまたはプロセスを特定。④ アプリケーションログを分析して根本原因を特定します。
Q overlay2 と aufs のどちらが良いですか?
A overlay2 のほうが優れており、Docker のデフォルトかつ唯一の推奨ストレージドライバです。aufs は非推奨となり、Docker 24 以降ではサポートされていません。overlay2 はより高いパフォーマンス、よりシンプルな実装、よりアクティブなコミュニティサポートを提供します。
Q コンテナのディスクが満杯になったとき、どうやってスペースを確保しますか?
A docker system df -v で最も容量を消費しているものを確認し、それに応じてクリーンアップします。① イメージ: docker image prune -a。② ビルドキャッシュ: docker builder prune。③ コンテナ: docker container prune。④ ボリューム: docker volume prune (注意: データが削除されるため慎重に)。⑤ すべて: docker system prune -a
Q コンテナの I/O が遅い問題をトラブルシューティングするには?
Adocker stats で BlockIO 列を確認。② ホストで iostat -x 1 を実行し、%util と await を確認。③ docker system df -v でストレージドライバの使用状況を確認。④ よくある原因: ログドライバがディスクを埋めている、overlay2 レイヤーが多すぎる、遅いディスクへの bind mount。
Q コンテナのネットワークレイテンシをテストするには?
A iperf3 を使用します。サーバーコンテナで iperf3 -s、クライアントコンテナで iperf3 -c server を実行し、スループットとレイテンシを測定します。コンテナ間でテストするには、それらが同じネットワーク上にあるか、--network host オプションを使用する必要があります。

📖 まとめ


📝 練習問題

  1. 基礎問題 (難易度 ⭐): stress コンテナを使って CPU 負荷をシミュレートし、docker stats で CPU 使用率の変化を監視してください。
  2. 応用問題 (難易度 ⭐⭐): docker system df -v でディスク使用量を分析し、docker system prune -a でクリーンアップを実行、ディスクスペースの差を比較してください。
  3. 挑戦問題 (難易度: ⭐⭐⭐): iperf3 を使って 2 つのコンテナ間のネットワーク帯域をテストし、bridge ネットワークと host ネットワークのパフォーマンス差を比較してください。
Web-Tutorial.com

Web-Tutorial 技術チーム

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

100%