コンテナのメモリと 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-1 | 2 GB | 最大1.5 GB |
| VDS-2 | 4 GB | 最大3 GB |
| VDS-3 | 8 GB | 最大6.5 GB |
| VDS-4 | 16 GB | 最大14 GB |
| VDS-5 | 24 GB | 最大21 GB |
| VDS-6 | 32 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)や、独自のプールを持つあらゆるサービスにも当てはまります。