言語を切り替える
テーマを切り替える

Docker リソース制限完全ガイド:コンテナのメモリリークでサーバーを落とさないために

スマホのアラートが鳴る——「サーバー応答なし」「CPU 100%」「SSH 接続タイムアウト」。VPN に 3 回つないで ssh を実行しても、タイムアウト。サーバーは完全にハングアップしていました。

強制再起動後、ログを確認すると、半年間稼働していたあるコンテナがメモリリークを起こし、500MB から 16GB まで肥大化してメモリを食いつぶしていました。SSH すら応答できない状態です。他の 3 つの正常なコンテナも巻き添えで停止——本番環境がダウンしました。2024 年には Docker 27.0.3 で深刻なメモリリーク Bug が報告され、68 個のコンテナが OOM Killer によって一斉に強制終了された事例もあります。

16GB
メモリリーク
コンテナのメモリリークが 500MB から 16GB まで急増し、サーバーのメモリを食いつぶした

本記事で解説するのは、1 つのコンテナがサーバー全体を道連れにするのを防ぐ方法です。cgroups の仕組みから --memory--cpus の実践設定、docker stats・cAdvisor・Prometheus の 3 大監視ツールまで、Docker リソース制限を一気通貫で理解できます。学び終えたら、メモリリークの兆候を検知したときにコンテナだけが停止し、サーバー全体が巻き添えになるのを避けられるはずです。

なぜコンテナがサーバーを道連れにするのか

Docker には「特性」があります——デフォルトでは、コンテナのリソース使用に上限がありません。自由に見えますが、その自由さのせいでホストのメモリと CPU を全部食い尽くし、全員が巻き添えになることもあります。

Docker 27.4.0 の実例:あるユーザーは、dockerd デーモンが数日で数百 MB から 8GB まで膨張し、サーバーの応答が著しく遅くなったと報告しています。Docker が不安定だと責めるのは早計です——問題は、上限を設定しないとコンテナが暴走し、好きなだけリソースを消費することにあります。

このとき Linux カーネルは「殺し屋」——OOM Killer(Out Of Memory Killer)——を起動します。システムメモリが不足すると、メモリ確保のために「最も適切」と判断したプロセスを強制終了します。各プロセスには oom_score というスコアが付き、高いほど殺されやすくなります。コンテナ内のプロセスはスコアが高めですが、Docker デーモンは oom_score_adj を -500 に設定して自分の優先度を下げるため、犠牲になるのは多くの場合あなたのコンテナです。

docker ps でコンテナが消え、docker logs で Exit Code 137 が出ていたら、128 + 9(SIGKILL)——つまり「強制終了された」という意味です。正常終了ではなく、カーネルに切り落とされたのです。

メモリリークの症状

  • コンテナのメモリ使用量が数百 MB から数 GB へと急上昇し続ける
  • サーバーが swap(スワップ領域)を大量に使い、ディスクランプが激しく点滅する
  • 他のコンテナの応答が遅くなり、最終的に停止する
  • 監視グラフに美しい右上がりの直線が現れる

2024 年、Storj コミュニティでは衝撃的な事例がありました。あるコンテナのメモリが通常の数百 MB から 37GB まで急増し、ストレージノード全体が危機に瀕しました。事前にメモリ上限を 1GB に設定していれば、OOM Killer がコンテナだけを処理し、サーバーは安定していたでしょう。

[画像:メモリリーク曲線図]
プロンプト:server memory usage graph showing sharp upward spike, red critical zone at 90%, dark background, monitoring dashboard style, high quality

cgroups:リソース制限の仕組み

Docker が cgroups でリソース制限を実現すると聞いたことがあっても、正体は何でしょうか。cgroups(Control Groups)は Linux カーネルの機能で、プロセスグループにリソース割当を設定します——各プロセスに「リソースカード」を配り、枠を超えたら使えなくなる、というイメージです。

Docker はコンテナ作成時に cgroups を自動生成し、コンテナのプロセスをそこに入れます。docker run -m 512m nginx を実行すると、裏では /sys/fs/cgroup/memory/docker/<コンテナID>/memory.limit_in_bytes に 536870912(512MB のバイト数)が書き込まれます。カーネルがこの値を読み、「このコンテナは最大 512MB、超えたら強制終了」と判断します。

cgroups v1 と v2 の違い

  • v1:メモリ・CPU・ディスク I/O を独立したサブシステムに分割。部門ごとにバラバラ管理
  • v2:統合管理で階層構造が明確。コンテナのような全体制御に適する
  • 旧システム(RHEL 7 など)は v1、新システム(Ubuntu 20.04+、RHEL 8+)はほぼ v2

コンテナの cgroups 設定を確認するには:

# コンテナの完全 ID を取得
docker inspect --format='{{.Id}}' my_container

# メモリ上限を確認(cgroups v1)
cat /sys/fs/cgroup/memory/docker/<コンテナID>/memory.limit_in_bytes

# CPU クォータを確認(cgroups v1)
cat /sys/fs/cgroup/cpu/docker/<コンテナID>/cpu.cfs_quota_us

初めてこれらのファイルを見たときは戸惑いました——リソース制限がファイルシステムで実現されているなんて。Linux の「Everything is a file」哲学です。カーネルが cgroups 設定をファイルとして公開し、Docker が値を書き、カーネルが読んで制限を実行する。エレガントな設計です。

[画像:cgroups 階層構造図]
プロンプト:Linux cgroups hierarchy diagram, containers grouped under docker cgroup, memory and CPU subsystems, tree structure, technical illustration, clean design, high quality

メモリ制限パラメータ完全解説

Docker のメモリパラメータは多いですが、実際によく使うのは限られています。順に解説します。

1. --memory / -m(ハードリミット、最重要)

命綱となるパラメータです。この値に達すると OOM Killer が発動し、コンテナは即座に強制終了されます。最小 6MB(実用性はほぼゼロ)ですが、本番では数百 MB 以上が現実的です。

# コンテナのメモリ上限を 512MB に設定
docker run -m 512m nginx

# GB 単位も可
docker run -m 2g my-app

適切な値の目安:アプリの通常時メモリ使用量を負荷テストで測り、1.2〜1.5 倍に設定。例えば 300MB なら 400〜450MB が妥当。低すぎると頻繁に OOM、高すぎると保護効果が薄れます。

2. --memory-swap(スワップ、誤解されやすい)

メモリ + スワップの合計を指定するパラメータで、スワップ単体のサイズではありません。

# 512MB メモリ + 512MB スワップ(合計 1GB)
docker run -m 512m --memory-swap 1g nginx

# スワップ無効(メモリのみ)
docker run -m 512m --memory-swap 512m nginx

# 無制限スワップ(危険!)
docker run -m 512m --memory-swap -1 nginx

--memory-swap を指定しない場合、デフォルトは swap = memory。つまり -m 512m なら合計 1GB(512MB メモリ + 512MB スワップ)まで使えます。

本番環境の推奨:スワップを無効化(--memory-swap--memory と同じ値に)するか、メモリの半分以下に制限。-1 は避けましょう。無制限スワップはディスクを壊します。

3. --memory-reservation(ソフトリミット)

「弾力枠」です。サーバーメモリに余裕があればこの値を超えて使えます。逼迫時はカーネルがこの値以下に押し戻そうとします。--memory より小さくする必要があります。

# ソフトリミット 750MB、ハードリミット 1GB
docker run -m 1g --memory-reservation 750m nginx

バッチ処理などで一時的にメモリを多く使うアプリに向いています。普段は少なく、ピーク時だけ増える場合に有効です。

4. --kernel-memory(カーネルメモリ、慎重に)

コンテナが使うカーネルメモリ(ネットワークバッファ、ファイルシキャッシュなど)を制限します。スワップ不可。自分が何をしているか分からない限り触らないでください——設定を誤ると起動すらできません。

5. --oom-kill-disable(危険パラメータ、要注意)

OOM Killer を無効化し、メモリ超過時もコンテナを殺さない設定です。一見良さそうに見えますが、大きな間違い。メモリが暴走しても殺されないと、サーバー全体のメモリが枯渇します。

# こうすると大惨事!(コンテナが無制限にメモリを消費)
docker run --oom-kill-disable nginx

# 使うなら必ずメモリ上限とセット
docker run -m 512m --oom-kill-disable nginx

いつ使うか?ほぼ使いません。DB の checkpoint など、突然 Kill されると困る特殊なアプリで、かつアプリ自身がメモリを制御できる場合のみ。

実例:AWS のあるユーザーは EC2 インスタンスがクラッシュ。調査の結果、メモリ上限のないコンテナが 30GB を消費し、インスタンスが完全に応答不能に。-m 2g を追加後、上限到達でコンテナだけが停止・再起動し、サーバーは安定しました。

[画像:メモリパラメータ関係図]
プロンプト:Docker memory parameters diagram, showing memory and swap relationship, visual chart with bars and labels, technical illustration, blue and orange colors, high quality

CPU 制限パラメータ完全解説

CPU 制限はメモリより穏やか——超えても Kill されず、速度が「絞られる」だけ。ただし CPU が暴走すればサーバーはカクつきます。

1. --cpus(最も直感的)

コンテナが使える CPU コア数を直接指定。小数も可。

# 最大 1.5 コア
docker run --cpus="1.5" nginx

# 0.5 コアのみ
docker run --cpus="0.5" my-app

内部では --cpu-period--cpu-quota で実装されています。1.5 なら、任意の時点で最大 1.5 コア分の計算能力——1 コアをフルに使い、もう 1 コアの 50% まで使えます。

2. --cpu-shares(相対重み、ハードリミットではない)

CPU スケジューリングの優先度。デフォルト 1024。CPU リソースが逼迫したときだけ効きます。サーバーに CPU 余裕があれば、コンテナは好きなだけ使えます。

# コンテナ A は B の 2 倍の CPU 時間
docker run --cpu-shares 2048 --name app_a my-app
docker run --cpu-shares 1024 --name app_b my-app

2 コアがフル稼働なら、A:B = 2:1 で配分——A が約 1.33 コア、B が 0.67 コア。CPU に余裕があれば両方フル速度で動きます。

いつ使うか?複数コンテナがあり、競合時に重要サービス(API をバックグラウンドより優先など)を守りたい場合。

3. --cpuset-cpus(特定コアに固定)

コンテナを特定の CPU コアに固定。他のコアは使えません。

# 0 番と 3 番のコアのみ
docker run --cpuset-cpus="0,3" nginx

# 2 番から 5 番のコア
docker run --cpuset-cpus="2-5" my-app

適用シーン:

  • NUMA アーキテクチャ:マルチソケットサーバーで同一ソケットのコアに固定し、ソケット間メモリアクセスを削減
  • キャッシュ効率:固定コアで CPU キャッシュヒット率を向上
  • 重要サービスの分離:DB を専用コアに固定し、他コンテナの干渉を回避

Kubernetes 環境では、8 コアサーバーの後半 4 コアを DB、前半 4 コアを Web に割り当て、性能が目に見えて向上した事例もあります。

4. --cpu-period--cpu-quota(細かい制御)

低レベルパラメータ。--cpus はこれらのラッパーです。

  • --cpu-period:CFS(完全公平スケジューラ)の周期。デフォルト 100000 マイクロ秒(100ms)
  • --cpu-quota:1 周期内にコンテナが使える CPU 時間(マイクロ秒)
# 100ms 周期のうち 50ms のみ CPU 使用可(0.5 コア相当)
docker run --cpu-period=100000 --cpu-quota=50000 nginx

# 以下と同等
docker run --cpus="0.5" nginx

通常は --cpus で十分。スケジューリング周期を短くして細かく制御したい場合のみ直接指定。

実例:あるサービスでスレッドプールのデッドループ Bug が発生し、コンテナの CPU が 800%(8 コアサーバー)に達しました。上限なしでサーバー全体が停止し、SSH も不通に。全コンテナに --cpus="2" を設定後、同様の Bug でも自分だけが遅くなり、他は安定しました。

[画像:CPU 制限比較テスト]
プロンプト:CPU usage comparison chart, with and without limits, before/after graph showing CPU spike prevention, performance monitoring dashboard, clean visualization, high quality

実践監視方案

リソース制限を設定しただけでは不十分。実際の使用量を把握しないと、OOM 発動後に気づくのは遅すぎます。

ツール 1:docker stats(組み込み、ゼロコスト)

最もシンプル。Docker 標準搭載。

# リアルタイム更新、Ctrl+C で終了
docker stats

# 1 回だけ出力、スクリプト向け
docker stats --no-stream

# 特定コンテナのみ
docker stats nginx_container mysql_container

出力例:

CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT     MEM %     NET I/O
a1b2c3d4e5f6   nginx     0.50%     45.2MiB / 512MiB     8.83%     1.2kB / 0B

長所:すぐ使える、追加インストール不要。
短所:現在値のみ、履歴・アラート・可視化なし。一時的な調査向け、長期監視には不向き。

ツール 2:cAdvisor(Google 製、コンテナ監視の定番)

cAdvisor(Container Advisor)はホスト上の全コンテナを自動検出し、CPU・メモリ・ネットワーク・ディスク I/O を収集。Web UI と Prometheus 形式の metrics エンドポイントを提供します。

起動は簡単:

docker run -d \
  --name=cadvisor \
  --restart=always \
  -p 8080:8080 \
  -v /:/rootfs:ro \
  -v /var/run:/var/run:ro \
  -v /sys:/sys:ro \
  -v /var/lib/docker/:/var/lib/docker:ro \
  -v /dev/disk/:/dev/disk:ro \
  gcr.io/cadvisor/cadvisor:latest

起動後、http://サーバーIP:8080 で各コンテナのリソース推移グラフを確認。http://サーバーIP:8080/metrics で Prometheus 形式データを取得。

長所:専門的・包括的・Prometheus エコシステム対応。
短所:直近 2 分程度のデータのみ保持。履歴トレンドには Prometheus が必要。

ツール 3:Prometheus + Grafana(エンタープライズ向け)

完全な監視体系:

  • cAdvisor:コンテナメトリクス収集
  • Prometheus:メトリクス取得・保存
  • Grafana:可視化 + アラート

完全な docker-compose.yml:

version: '3.8'

services:
  cadvisor:
    image: gcr.io/cadvisor/cadvisor:latest
    container_name: cadvisor
    ports:
      - "8080:8080"
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
      - /dev/disk/:/dev/disk:ro
    restart: always

  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
    restart: always

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - "3000:3000"
    volumes:
      - grafana_data:/var/lib/grafana
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    restart: always

volumes:
  prometheus_data:
  grafana_data:

対応する prometheus.yml

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'cadvisor'
    static_configs:
      - targets: ['cadvisor:8080']

デプロイ後:

  1. Prometheus が 15 秒ごとに cAdvisor からデータを収集
  2. Grafana は http://サーバーIP:3000(デフォルト admin/admin)
  3. Prometheus データソースを追加(http://prometheus:9090
  4. Grafana ダッシュボードテンプレートをインポート(Docker 向け Dashboard ID: 19908 推奨)

重要な監視メトリクス

  • container_memory_usage_bytes:現在のメモリ使用量
  • container_memory_max_usage_bytes:履歴最大メモリ使用量
  • container_cpu_load_average_10s:10 秒平均 CPU 負荷
  • container_fs_io_time_seconds_total:ディスク I/O 時間

メモリ使用率 80% 超でメールや Slack 通知のアラートを設定すれば、問題が爆発する前に兆候を掴めます。

正直、構築は少し手間ですが、一度整えれば長持ちします。私が管理する 20 以上のコンテナは Grafana で監視し、夜中に起こされることはなくなりました。

[画像:Grafana コンテナ監視ダッシュボード]
プロンプト:Grafana dashboard showing Docker container metrics, memory and CPU graphs, clean modern UI, dark theme, monitoring panels with colorful charts, high quality

メモリリーク診断の完全フロー

監視アラートが鳴る、またはコンテナが突然停止——素早く原因を特定する手順です。

ステップ 1:異常の発見

まず docker stats でどのコンテナのメモリが急増しているか確認:

docker stats --no-stream | grep -v "0.00%"

あるコンテナのメモリが上限に近づいている?OOM Killer に殺された履歴を確認:

# コンテナイベントログ
docker events --filter 'event=oom' --since '24h'

# 終了ステータス
docker inspect <コンテナ> --format='{{.State.ExitCode}}'
# 137 なら OOM Killer による強制終了

ステップ 2:メモリ使用量の分析

コンテナ内でどのプロセスがメモリを消費しているか確認:

# コンテナに入る
docker exec -it <コンテナ> /bin/bash

# プロセスのメモリ順(top/htop が必要)
top -o %MEM

# または ps
ps aux --sort=-%mem | head -n 10

Java アプリなら heap dump をエクスポート:

# Java プロセス PID を取得
jps

# heap dump をエクスポート
jcmd <PID> GC.heap_dump /tmp/heap.hprof

# ファイルをコピーして分析
docker cp <コンテナ>:/tmp/heap.hprof ./

ステップ 3:応急処置

サービスに影響が出ている場合、まず一時的に緩和:

# コンテナ再起動(一時データは失われる)
docker restart <コンテナ>

# 稼働中なら動的にメモリ上限を変更
docker update --memory 1g --memory-swap 1g <コンテナ>

# 未使用リソースのクリーンアップ(注意:未使用イメージ・コンテナを削除)
docker system prune -a

ステップ 4:根本対策

応急処置は止血。本治療は以下:

  1. アプリコードの修正:接続未クローズ、キャッシュ無限増加、大オブジェクト未解放など、リークの根本原因を修正
  2. リソース制限の設定:未設定なら --memory を追加
  3. 監視の導入:Prometheus + Grafana を構築し、問題が顕在化する前にアラート
  4. 自動再起動--restart=on-failure:3 で OOM 後に最大 3 回自動再起動

コマンド早見表

# 全コンテナのリソース制限設定を確認
docker ps --format "{{.Names}}" | xargs docker inspect \
  --format='{{.Name}}: Memory={{.HostConfig.Memory}} CPU={{.HostConfig.NanoCpus}}'

# コンテナの再起動回数
docker inspect --format='{{.RestartCount}}' <コンテナ>

# 詳細ログ(最後 100 行)
docker logs --tail 100 <コンテナ>

# メモリ使用の内訳
docker stats --no-stream --format \
  "table {{.Name}}\t{{.MemUsage}}\t{{.MemPerc}}" <コンテナ>

実例振り返り:Storj の 37GB メモリリーク事例では、以下の手順で対処しました:

  1. メモリ急増を発見後、docker restart で一時復旧
  2. -m 1g を追加し、再発時のホスト巻き添えを防止
  3. コンテナログと heap dump をエクスポートし、開発チームに分析依頼
  4. Bug 修正版リリース後、イメージを更新して再デプロイ
  5. cAdvisor 監視を導入し、メモリ使用率 70% 超でアラート

大変でしたが、教訓を活かして以降は同様の問題は発生していません。

[画像:メモリ診断フロー図]
プロンプト:flowchart showing memory leak diagnosis process, step by step from detection to resolution, arrows connecting boxes, clean infographic style, blue and green colors, high quality

ベストプラクティスと落とし穴

パラメータとツールを一通り見たところで、本番環境での正しい使い方をまとめます。

本番環境必須チェックリスト

全コンテナにメモリ上限を設定
僥倖は禁物。Nginx の静的配信でも 512MB を設定。保守的でも、事後対応よりマシです。

開発環境でも本番相当の制限を再現
ローカルで上限なし、本番でメモリ不足——そんなパターンを避ける。本番の 80% 程度で開発し、事前に問題を発見。

定期的なリソース使用レビュー
月 1 回 docker stats を確認。需要変化に応じて上限を増減。

OOM Killer を無効化しない
アプリが確実にメモリを制御できる場合以外、--oom-kill-disable は触らない。自殺行為に近いパラメータです。

無制限スワップを使わない
--memory-swap -1 はサーバーに地雷を埋める行為。スワップ乱用はディスクを壊し、OOM Killer でコンテナだけ止める方がマシです。

メモリ上限を低くしすぎない
実需要より低いと頻繁 OOM で可用性が下がる。先に負荷テスト、後に上限設定。

Docker Compose での正しい設定

services:
  web:
    image: nginx:latest
    deploy:
      resources:
        limits:
          cpus: '1.5'
          memory: 512M
        reservations:
          cpus: '0.5'
          memory: 256M
    restart: on-failure:3

deploy フィールド(Docker Compose v3 構文)を使用。limits はハードリミット、reservations はソフトリミット。普段 256MB、繁忙時 512MB まで使える設定例です。

複数コンテナの一括管理

マイクロサービス群をリソースプールで統一管理するには cgroup-parent

# 親 cgroups を作成し、合計リソースを制限
docker run --cgroup-parent=/my-services -m 2g service-a
docker run --cgroup-parent=/my-services -m 2g service-b
# 2 コンテナが親 cgroups を共有し、合計メモリが親の上限を超えない

関連コンテナが 1 つのビジネスユニットを構成し、全体でリソースを制御したい場合に有効。

リソース制限の経験則

アプリ種別メモリ上限の目安CPU 上限の目安
Nginx 静的配信256-512MB0.5-1 コア
Node.js API512MB-1GB1-2 コア
Java マイクロサービス1-2GB2-4 コア
データベース(MySQL/PostgreSQL)2-4GB2-4 コア
メッセージキュー(RabbitMQ/Kafka)1-2GB1-2 コア

保守的な目安です。実際は业务量次第。負荷テストでピーク使用量を観測し、1.5 倍を上限にするのが安全です。

Kubernetes リソース管理との比較

Kubernetes を使ったことがあれば、requestslimits は Docker パラメータとよく似ています:

  • requests:Docker の --memory-reservation に相当
  • limits:Docker の --memory に相当

K8s は YAML で統一管理できる規範性、Docker は docker update でいつでも調整できる柔軟性——それぞれの強みがあります。

最後のアドバイス

リソース制限は「一度設定すれば永久有効」ではありません。アプリは変わり、业务量は増え、監視データが上限の見直しかコード最適化かを教えてくれます。定期的に見直し、設定を形骸化させないでください。

[画像:リソース制限設定比較表]
プロンプト:comparison table showing Docker resource limits best practices, checkmarks and crosses, clean infographic style, professional layout, high quality

まとめ

冒頭の話に戻りましょう。午前 3 時のアラートで起こされ、コンテナがサーバーをダウンさせた——その教訓から、Docker のデフォルト「自由」は罠だと学びました。上限を設定しなければ、サーバーの生死をコンテナに委ねることになります。

振り返ると、防御体系は明確です:

第 1 防衛線:リソース制限(予防)
各コンテナに --memory--cpus を設定。暴走時はコンテナだけが停止し、サーバー全体を巻き添えにしない。最も基本かつ重要なステップ。

第 2 防衛線:監視とアラート(発見)
docker stats で現在値、cAdvisor + Prometheus + Grafana でトレンドと履歴。メモリ使用率 80% 超でアラートすれば、48 時間前に兆候を掴めます。

第 3 防衛線:診断フロー(対応)
問題が起きても慌てない。異常発見 → 使用量分析 → 応急処置 → 根本対策。コマンド一覧は本記事に揃っています。

cgroups の仕組みから --memory-swap の詳細、Docker Compose 設定、Kubernetes 比較まで、Docker リソース制限の要点はここまでカバーしました。あとは実行するだけです。

今すぐこの 3 つを

  1. 本番環境を確認。上限未設定のコンテナを洗い出す:
docker ps --format "{{.Names}}" | xargs docker inspect \
  --format='{{.Name}}: Memory={{.HostConfig.Memory}} CPU={{.HostConfig.NanoCpus}}'

Memory=0 のコンテナは時限爆弾です。

  1. 監視を導入。記事内の docker-compose.yml をコピーして起動。30 分で完了。

  2. カレンダーにリマインダー。月 1 回、1 時間 docker stats でリソース使用をレビュー。

正直、午前 3 時のアラートで学ばせてほしくはありません。リソース制限は早めに設定するほど楽です。問題が起きてから後悔しないように。

Docker リソース制限の完全設定フロー

コンテナのメモリリークでサーバーを落とさないために。cgroups の仕組みから --memory・--cpus の実践設定、監視まで

⏱️ 目安時間: 1 時間

  1. 1

    ステップ1: 問題の深刻さと cgroups の仕組みを理解する

    問題の深刻さ:
    • コンテナのメモリリークが 500MB から 16GB まで急増
    • サーバーのメモリを食いつぶし、SSH すら応答しなくなる
    • 他の正常なコンテナも巻き添えで停止し、本番環境がダウン

    cgroups の仕組み:
    • Linux カーネルの cgroups 機構がコンテナのリソース使用を制御
    • Docker は cgroups で CPU・メモリ・I/O などを制限
    • 1 つのコンテナがサーバー全体を道連れにするのを防ぐ

    2024 年、Docker 27.0.3 では深刻なメモリリーク Bug が報告され、68 個のコンテナが Linux カーネルの OOM Killer によって一斉に強制終了された。
  2. 2

    ステップ2: リソース制限を設定する:メモリと CPU

    メモリ制限:
    • --memory パラメータでメモリ上限:docker run --memory=512m container-name
    • docker-compose でリソース制限:deploy.resources.limits.memory: 512m
    • メモリスワップ制限:--memory-swap

    CPU 制限:
    • --cpus パラメータで CPU 上限:docker run --cpus=1.0 container-name
    • --cpu-shares で CPU 重みを設定
    • docker-compose で設定:deploy.resources.limits.cpus: '1.0'

    制限の確認:
    • docker stats でコンテナのリソース使用状況を確認
    • 制限が有効になっていることを確認
  3. 3

    ステップ3: 監視を導入し、ベストプラクティスを適用する

    監視:
    • docker stats でリアルタイム監視:docker stats container-name
    • cAdvisor で可視化:
    docker run -d -p 8080:8080 --name=cadvisor google/cadvisor
    • Prometheus + Grafana で本番レベルの監視とアラート:
    Prometheus で cAdvisor のメトリクスを収集し、Grafana で可視化

    ベストプラクティス:
    • 本番環境では必ずリソース制限を設定
    • 適切な上限値(メモリ・CPU)を設定
    • 監視とアラートを構成
    • 定期的にコンテナのリソース使用状況を確認(月 1 回、1 時間 docker stats を見る)
    • 異常を早期に対処

FAQ

なぜ Docker リソース制限を設定する必要があるのか?
問題の深刻さ:
• コンテナのメモリリークが 500MB から 16GB まで急増
• サーバーのメモリを食いつぶし、SSH すら応答しなくなる
• 他の正常なコンテナも巻き添えで停止し、本番環境がダウン

2024 年、Docker 27.0.3 では深刻なメモリリーク Bug が報告され、68 個のコンテナが Linux カーネルの OOM Killer によって一斉に強制終了された。

リソース制限により、1 つのコンテナがサーバー全体を道連れにするのを防げます。メモリリークの兆候があればコンテナだけが停止し、サーバー全体が巻き添えになるのを避けられます。
Docker コンテナのリソース制限はどう設定するか?
メモリ制限:
• --memory パラメータ:docker run --memory=512m container-name
• docker-compose:deploy.resources.limits.memory: 512m
• メモリスワップ制限:--memory-swap

CPU 制限:
• --cpus パラメータ:docker run --cpus=1.0 container-name
• --cpu-shares で CPU 重みを設定
• docker-compose:deploy.resources.limits.cpus: '1.0'

制限の確認:
• docker stats でリソース使用状況を確認
• 制限が有効になっていることを確認
Docker コンテナのリソース使用状況はどう監視するか?
監視:

docker stats によるリアルタイム監視:
• docker stats container-name

cAdvisor による可視化:
• docker run -d -p 8080:8080 --name=cadvisor google/cadvisor

Prometheus + Grafana による本番レベルの監視とアラート:
• Prometheus で cAdvisor のメトリクスを収集
• Grafana で可視化

監視の導入:記事内の docker-compose.yml をそのままコピーして起動すれば、30 分で完了。

定期確認:月 1 回、1 時間 docker stats を見て、リソース使用が妥当かレビューする。
Docker リソース制限のベストプラクティスは?
ベストプラクティス:
• 本番環境では必ずリソース制限を設定
• 適切な上限値(メモリ・CPU)を設定
• 監視とアラートを構成
• 定期的にコンテナのリソース使用状況を確認(月 1 回、1 時間 docker stats を見る)
• 異常を早期に対処

リソース制限は早めに設定するほど楽です。問題が起きてから後悔しないように。カレンダーにリマインダーを入れ、月 1 回 docker stats でレビューしましょう。

8分で読めます · 公開日: 2025年12月18日 · 更新日: 2026年6月8日

関連記事

コメント

GitHubアカウントでログインしてコメントできます