Skip to content
VDS · Dockerとコンテナ

コンテナのメモリと CPU 制限

コンテナにメモリと CPU の上限を設定する方法、上限がないと 1 つのサービスが他をすべて巻き添えにする理由、プロセスがカーネルに強制終了されたことを見分ける方法について説明します。

更新日 2026年8月23日

既定では、コンテナはマシン上のすべてのメモリとすべてのコアを使用できます。2ギガバイトのVDS-1では、これは予想どおりの結果になります。1つのサービスが肥大化し、カーネルがプロセスの強制終了を始め、停止するのはそれではなく隣にあるデータベースです。

上限の設定方法

services:
  app:
    image: ghcr.io/example/app:1.5.0
    deploy:
      resources:
        limits:
          memory: 768M
          cpus: "1.0"
        reservations:
          memory: 256M

Composeは、単純な docker compose up -d でも deploy.resources.limits を適用します。docker run で同等の設定は次のとおりです。

docker run -d --memory 768m --cpus 1.0 --memory-swap 768m <image>

--memory-swap を --memory と同じ値に設定すると、スワップが禁止されます。何時間もほとんど動かないマシンより、正直にクラッシュするほうがましです。

どれだけ割り当てるか

ご利用のティアを基準にし、システム用に余裕を残してください。

ティアメモリコンテナ上限の妥当な合計
VDS-12 GB最大1.5 GB
VDS-24 GB最大3 GB
VDS-38 GB最大6.5 GB
VDS-416 GB最大14 GB
VDS-524 GB最大21 GB
VDS-632 GB最大29 GB

残りはシステム、ファイルキャッシュ、Docker自体に必要です。上限の合計がメモリ量を超えているのは、設定ミスではなく、起こるべくして起こる災害です。

CPUについて: cpus: "1.0" は1コア全体です。VDS-1はシングルコアなので、そこではCPUを制限する意味はほとんどありませんが、VDS-4以上ではサーバー構成が6コアすべてを占有しないようにする価値があります。

実際に消費されるもの

docker stats --no-stream
docker stats --no-stream --format "table {{.Name}}\t{{.MemUsage}}\t{{.CPUPerc}}"
free -h

負荷がかかった状態でサービスを1日監視し、上限をピークのおよそ1.5倍に設定してください。厳しすぎる上限は、上限がないよりも悪いです。サービスは、最も必要としているまさにその瞬間に再起動します。

全画面の htop と btop は「Screen」コンソール(VNC)でのみ動作します。テキストコンソールはウィンドウサイズを渡さず、常に80×24で、インターフェースが崩れます。テキストコンソールでの簡単な測定には、docker stats --no-stream と free -h を使用してください。

メモリによって強制終了されたかどうかの見分け方

docker inspect -f '{{.State.ExitCode}} {{.State.OOMKilled}}' <container>
sudo dmesg -T | grep -i -E "out of memory|killed process"

終了コード137と OOMKilled: true が同時に現れれば、紛れもない判定です。そこから選択肢は2つあります。上限が低すぎたのなら引き上げるか、アプリケーションが増え続ける理由を突き止めるかです。リークはメモリを追加しても治らず、先延ばしになるだけです。

Javaとその他の特殊なケース

Java仮想マシンは、コンテナの上限ではなくホストのメモリを参照することが今でもあり、存在しない余裕を見込んでヒープをサイズ設定します。明示的に設定してください。

environment:
  JAVA_TOOL_OPTIONS: "-Xmx512m -Xms256m"

同じことはPostgreSQL(shared_buffers)や、独自のプールを持つあらゆるサービスにも当てはまります。

よくある間違い

  • 上限をまったく設定していない。 「マシンがフリーズして何も応答しない」の最も一般的な原因です。
  • 上限はあるが、ヘルスチェックがない。 コンテナが強制終了され、再起動されませんでした。restart: unless-stopped と healthcheck を追加してください。詳しくはコンテナの更新をご覧ください。
  • ディスクのことを忘れている。 メモリは制限したものの、書き込みが上限に達します。詳しくはディスク速度をご覧ください。