DockerコンテナのOOM KillerによるExit Code 137の原因とメモリ上限設計

Docker DevOps Infrastructure Linux
結論

Exit Code 137 は Linux OOM Killer による SIGKILL 強制停止が原因です。

# Docker公式仕様:コンテナが OOM Killer で殺されたか確認するコマンド
docker inspect --format='{{.State.OOMKilled}}' my_app_container

# 出力が true の場合: Linux OOM Killer がプロセスを殺害した
# true
# docker-compose.yml での安全なメモリリミット設定例
version: '3.8'
services:
  app:
    image: node:22-slim
    deploy:
      resources:
        limits:
          memory: 1g        # 超過で OOM Killer が起動する上限
        reservations:
          memory: 512m      # 確保するベースメモリ

Docker公式仕様:Exit Code 137 の正体

Docker公式ドキュメント(docs.docker.com/engine/containers/resource_constraints/)の規定通り、コンテナが Exit Code 137 で停止した場合、これは Linux のシグナル計算式に基づく強制終了を意味します。

Exit Code 137 = 128 + SIGKILL (Signal 9)

コンテナ(cgroup)に割り当てられたメモリ上限(memory limit)を超えた瞬間に、Linux カーネルの OOM (Out Of Memory) Killer が介入し、最優先でそのコンテナのメインプロセスに対して回避不可の SIGKILL を発行して強制殺害します。


実際に起こる障害:アプリログに残らない「コンテナ沈黙停止」事故

開発者が Web サービスのコンテナダウンに対応する際、コンテナのアプリケーションログ(docker logs)を確認してもエラーメッセージやスタックトレースが一切残っていないため原因が特定できず、無限にクラッシュループ(CrashLoopBackOff)を繰り返す大障害 が発生します。

プロセスが Catch 不可の SIGKILL で即座に殺されるため、アプリ側のエラーハンドラーすら通過しないことが理由です。


調査・解決手順

  1. docker inspect --format='{{.State.OOMKilled}}' <container_id> を実行し、結果が true であることを特定する
  2. dmesg -T | grep -i oom をホスト Linux 上で実行し、カーネルの OOM Killer ログを確認する
  3. docker-compose.ymldeploy.resources.limits.memory を適切な値(例: Node.js なら 1GB 以上)に引き上げるか、アプリケーション内のメモリリーク(キャッシュ無制限保持等)を修復する