Reported symptoms
- Container is in
Exited (137)state. docker inspectshowsOOMKilled: true.- Application logs stop abruptly without an error message.
- Restart policy may show a crash loop.
Evidence provided
$ docker ps -a
CONTAINER ID STATUS NAMES
abc123def456 Exited (137) 2 minutes ago api
$ docker inspect abc123def456 | grep -i oom
"OOMKilled": true,
$ docker logs abc123def456 --tail 50
# (no recent log lines — the process was killed before flushing)
Root cause
The container’s cgroup memory limit was exceeded. The kernel’s OOM-killer killed the process. The application did not handle the SIGKILL gracefully, so no cleanup messages were logged.
Resolution
- Measure actual memory usage.
docker stats api --no-stream- Compare to the configured
mem_limit. - Increase the memory limit.
- Update
compose.yml:mem_limit: 1g(was 512m) - Or use the Compose shorthand:
mem_limit: 1G. docker compose up -dto apply.- Investigate the leak.
- If usage is unbounded, the limit only delays the crash. Profile the application to find the leak.
docker exec api ps auxto see RSS per process.docker exec api sh -c "cat /proc/1/status | grep VmRSS"for the container's PID 1.- Set appropriate restart policy.
restart: on-failure:5(5 attempts, then stop). Prevents crash loops from masking other issues.
Verification
- Container stays running under normal load.
docker psshowsUp X minutes. - Memory usage stays below the limit.
docker statsshows usage below the limit with headroom. - The leak (if any) is fixed. Memory usage is stable over time.
- The OOMKilled flag is false.
docker inspectdoes not showOOMKilled: truein subsequent runs.
Prevention
- Set memory limits based on actual usage + headroom, not guesswork.
- Monitor memory usage; alert at 80% of the limit.
- Investigate growth; memory usage that increases over time is a leak.
- Use memory reservations (
mem_reservation) for soft limits.