Linux Labs

Containers: Docker and compose / Stage 10 of 11

Limits, OOMKilled and the user in a container

Not running Starting usually ~20 s
Leave the lesson

Step 2 of 9 · theory · 6 min

The memory limit and the OOM killer

The report container was created with the --memory 32m option. That option is what cut the build off.

A container's processes are ordinary processes of the machine. Docker puts them into a cgroup — a group for which the kernel counts and limits resources. --memory 32m is a memory ceiling for all of the container's processes together. docker inspect keeps it in bytes: .HostConfig.Memory for report is 33554432.

The build keeps the whole of sales.csv in memory and hits the ceiling. The kernel first frees whatever it can in the group, and when there is nothing left to free, it calls the OOM killer: it picks the largest process in the group and ends it with the SIGKILL signal, number 9. This signal cannot be caught, so build.sh had no time to print anything, and the report.sh shell wrote just Killed.

A process killed by a signal ends with code 128 + the signal number, and for SIGKILL that is 137. report.sh returned the build's code, the container exited with the same one, and docker marked in .State.OOMKilled that the kernel had killed a process for lack of memory. The kernel itself logs every such case:

bash
sudo journalctl -k | grep -i 'out of memory'
# Memory cgroup out of memory: Killed process 1479 (sh) …

Memory cgroup at the start of the line means the group's memory ran out; the machine may have free memory at that moment.

Note

If the main process itself is killed and the container exits at once, docker sometimes misses the event from the kernel: code 137, yet OOMKilled is false. The line in journalctl -k is always there.

Check yourself 1 question

You stopped a container with docker stop. After 10 seconds, docker ps -a shows Exited (137), and OOMKilled is false. Where does code 137 come from?

  • A missed event would leave an out of memory line in sudo journalctl -k. Here the code appeared exactly 10 seconds after docker stop — the time docker waits before sending SIGKILL.

  • A process ended by SIGTERM (number 15) gets code 128 + 15 = 143. 137 is 128 + 9, SIGKILL.

docker stop sends the main process SIGTERM and waits 10 seconds. If the process has not ended, docker sends SIGKILL, and the code is the same 137. So 137 alone does not prove a memory shortage: check OOMKilled and the kernel log.

Key points

  • --memory is a memory ceiling for all of a container's processes; in docker inspect it is .HostConfig.Memory, in bytes.
  • Outgrow the ceiling, and the OOM killer ends the largest process in the group with SIGKILL: code 128 + 9 = 137.
  • Code 137 also follows docker stop; a memory shortage is confirmed by OOMKilled and an out of memory line in the kernel log.
Ubuntu 24.04
Loading…