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

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

深夜3時の悪夢

深夜3時、けたたましいアラートで叩き起こされました。「サーバー応答なし」。
SSHも繋がらず、最終的に物理的な再起動を余儀なくされました。

ログを見て血の気が引きました。原因は、半年前にデプロイした地味なバッチ処理コンテナ。メモリリークを起こし、500MBだったメモリ消費が16GBまで膨れ上がり、サーバーのリソースを食い尽くしていたのです。他の重要なサービスも巻き添えで全滅していました。

16GB
メモリリーク

Dockerコンテナは、デフォルトではホストのリソースを無制限に使えます。これは「自由」ではなく「リスク」です。
この記事では、私のような失敗をしないために、コンテナに適切なリソース制限(Resource Limits)をかける方法と、それを監視する仕組みについて解説します。

なぜリソース制限が必要なのか?

ホストOSを守る「防波堤」

Linuxカーネルには「OOM Killer (Out Of Memory Killer)」という暗殺者が住んでいます。システム全体のメモリが足りなくなると、彼は目につくプロセスを無差別に殺してメモリを確保しようとします。
もしコンテナに制限をかけていなければ、コンテナが好き放題メモリを使ってシステムを枯渇させ、結果として重要なSSHデーモンやデータベースまでOOM Killerに殺される可能性があります。

コンテナに上限(Limit)を設定しておけば、メモリリークしてもそのコンテナだけが死にます。ホストOSや他のコンテナは無傷です。これがリソース制限の真の目的です。

メモリ制限のパラメータ

--memory / -m (ハードリミット)

最も基本的かつ重要な設定です。コンテナが使えるメモリの絶対上限を決めます。

# 上限を512MBに設定
docker run -d --name my-app --memory 512m nginx

コンテナが512MBを超えようとすると、OOM Killerによってコンテナだけが即座にKillされます(Exit Code 137)。残酷に見えますが、サーバー全体が死ぬよりマシです。

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

「できればこのくらいに抑えてね」という予約値です。

docker run -d --memory 1g --memory-reservation 512m my-app

ホストのメモリに余裕がある時は1GBまで使えますが、余裕がなくなると512MBまで圧縮しようとします(キャッシュ解放など)。柔軟な運用が可能です。

--memory-swap (スワップ設定の罠)

これは誤解しやすいパラメータです。「メモリ + スワップ」の合計値を指定します。

# メモリ512MB + スワップ512MB = 合計1GBまで利用可能
docker run -d --memory 512m --memory-swap 1g my-app

もし --memory-swap を指定しない場合、デフォルトでは「メモリと同量のスワップ」が割り当てられます(つまり合計2倍)。
推奨:本番環境ではスワップを使わせたくないことが多いです。その場合は --memory と同じ値を設定します(スワップ0になります)。

CPU制限のパラメータ

--cpus (推奨)

最も直感的な設定です。「CPUコア何個分を使っていいか」を指定します。

# 1.5コア分まで利用可能
docker run -d --cpus="1.5" my-app

例えば4コアのサーバーで 1.5 を指定すると、コンテナは負荷が高い時に最大で1.5コア分の計算能力を使えます。上限を超えるとCPU時間が割り当てられなくなり、処理が遅くなります(Killはされません)。

--cpuset-cpus (特定のコアに固定)

コンテナを特定のCPUコアだけで動かしたい場合に使います(CPU Pinning)。

# 0番と3番のコアだけを使う
docker run -d --cpuset-cpus="0,3" my-app

NUMAアーキテクチャのサーバーなどで、メモリキャッシュ効率を極限まで高めたい時に有効です。

Docker Composeでの設定例(バージョン3)

docker-compose.yml では deploy セクションに記述します。

version: '3.8'
services:
  web:
    image: nginx
    deploy:
      resources:
        limits:
          cpus: '0.50'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M
  • limits: 絶対超えてはいけない上限(ハードリミット)。
  • reservations: 確保したい保証値(ソフトリミット)。

運用とモニタリング

制限をかけたら、次はその制限が適切かどうかを監視しましょう。

1. docker stats (簡易チェック)

リアルタイムでリソース使用状況が見られます。

docker stats
CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT     MEM %
a1b2c3d4e5f6   nginx     0.05%     24MiB / 512MiB        4.68%

LIMIT に対して USAGE がカツカツになっていないかチェックしましょう。

2. cAdvisor + Prometheus + Grafana (本格監視)

本番運用なら、Google製の cAdvisor を使うのが鉄板です。コンテナのリソース情報を収集し、Prometheus等のメトリクス収集ツールに渡してくれます。

cAdvisorの起動:

docker run -d \
  --volume=/:/rootfs:ro \
  --volume=/var/run:/var/run:ro \
  --volume=/sys:/sys:ro \
  --volume=/var/lib/docker/:/var/lib/docker:ro \
  --publish=8080:8080 \
  --name=cadvisor \
  google/cadvisor:latest

これで http://localhost:8080 にアクセスすれば、グラフィカルなリソースグラフが見られます。あとはGrafanaでカッコいいダッシュボードを作って、メモリ使用率80%超えでSlack通知を送れば完璧です。

まとめ:安全な運用のためのチェックリスト

  1. 全てのコンテナに --memory 制限を入れる:最低限の防衛策です。見積もりが難しければ、少し大きめ(1GBとか)でもいいので設定しましょう。「無限」よりはマシです。
  2. CPU制限は必要に応じて:CPUを食いつぶすバグ(無限ループなど)対策として --cpus も設定しておくと安心です。
  3. 監視する:リミットに張り付いていないか、定期的にチェックしましょう。

コンテナに制限をかけることは、コンテナを縛ることではありません。あなたのサーバーと、安眠を守るための「命綱」なのです。

Dockerリソース制限の実践フロー

メモリ・CPU制限の設定から監視まで

⏱️ Estimated time: 15 min

  1. 1

    Step1: ステップ1:ベースラインの測定

    アプリを負荷テストし、docker stats で通常時とピーク時のメモリ・CPU使用量を把握します。
  2. 2

    Step2: ステップ2:制限値の決定と設定

    ピーク時のメモリ使用量の1.2〜1.5倍程度を --memory に設定します。CPUは --cpus でコア数制限をかけます。
  3. 3

    Step3: ステップ3:OOM時の挙動確認

    わざとメモリを食いつぶすプログラムを走らせて、設定通りにコンテナだけが Kill される(Exit 137)ことを確認します(カオスエンジニアリング)。
  4. 4

    Step4: ステップ4:継続的な監視

    cAdvisorなどを導入し、リソース使用率が閾値を超えたらアラートが飛ぶように設定します。

FAQ

メモリ制限を超えるとどうなりますか?
OOM Killer(Out Of Memory Killer)により、コンテナプロセスが強制終了(Kill)されます。コンテナの状態は「Exited (137)」になります。これは異常ではなく、ホストを守るための正常な動作です。
--memory-swap を設定しないとどうなりますか?
デフォルトでは、設定した --memory の2倍の量が割り当てられます(メモリ512MBならスワップも512MB、合計1GB)。スワップを使わせたくない場合は、--memory と同じ値を --memory-swap に設定してください。
docker-compose up時に「deploy」キーが無視されます。
docker-composeのバージョンや、互換性モード(compatibility mode)の設定によります。v3系を使う場合、本来はSwarm mode用ですが、`docker-compose --compatibility up` とすることで単一ホストでもリソース制限を有効にできます。

3 min read · 公開日: 2025年12月18日 · 更新日: 2026年1月22日

コメント

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

関連記事