Linux Labs

Контейнеры: Docker и compose / Ступень 10 из 11

Лимиты, OOMKilled и пользователь в контейнере

Не запущена Запускается обычно ~20 с
Выйти из урока

Шаг 2 из 9 · теория · 6 мин

Лимит памяти и OOM killer

Контейнер report создан с ключом --memory 32m. Этот ключ и оборвал сборку.

Процессы контейнера — обычные процессы машины. Docker собирает их в cgroup — группу, которой ядро считает и ограничивает ресурсы. --memory 32m — потолок памяти для всех процессов контейнера вместе. В docker inspect он хранится в байтах: .HostConfig.Memory у report — 33554432.

Сборка держит sales.csv в памяти целиком и упирается в потолок. Ядро сначала освобождает в группе всё, что может, а когда освобождать нечего, зовёт OOM killer: тот выбирает в группе самый большой процесс и завершает его сигналом SIGKILL с номером 9. Этот сигнал нельзя перехватить, поэтому build.sh не успел ничего напечатать, а оболочка report.sh написала только Killed.

Процесс, убитый сигналом, завершается с кодом 128 + номер сигнала, и для SIGKILL это 137. report.sh вернул код сборки, контейнер вышел с ним же, а docker отметил в .State.OOMKilled, что ядро убивало процесс за нехватку памяти. Само ядро пишет каждый такой случай в журнал:

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

Memory cgroup в начале строки значит, что кончилась память группы; у машины в это время память может быть свободна.

Заметка

Если убит сам главный процесс и контейнер сразу завершился, docker иногда не успевает получить событие от ядра: код 137, а OOMKilled — false. Строка в journalctl -k есть всегда.

Проверь себя 1 вопрос

Ты остановил контейнер командой docker stop. Через 10 секунд docker ps -a показывает Exited (137), а OOMKilled — false. Откуда код 137?

  • Пропущенное событие оставило бы строку out of memory в sudo journalctl -k. Здесь код появился ровно через 10 секунд после docker stop — столько docker ждёт, прежде чем послать SIGKILL.

  • Процесс, завершённый SIGTERM (номер 15), получает код 128 + 15 = 143. 137 — это 128 + 9, SIGKILL.

docker stop посылает главному процессу SIGTERM и ждёт 10 секунд. Процесс не завершился — docker посылает SIGKILL, и код тот же, 137. Поэтому 137 само по себе нехватку памяти не доказывает: смотри OOMKilled и журнал ядра.

Главное в шаге

  • --memory — потолок памяти для всех процессов контейнера; в docker inspect это .HostConfig.Memory в байтах.
  • Перерос потолок — OOM killer завершает самый большой процесс группы сигналом SIGKILL: код 128 + 9 = 137.
  • Код 137 бывает и после docker stop; нехватку памяти подтверждают OOMKilled и строка out of memory в журнале ядра.
Ubuntu 24.04
Загрузка…