Контейнер 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, что ядро убивало процесс за нехватку памяти. Само ядро пишет каждый такой случай в журнал:
Memory cgroup в начале строки значит, что кончилась память группы; у машины в это время память может быть свободна.
Если убит сам главный процесс и контейнер сразу завершился, docker иногда не успевает получить событие от ядра: код 137, а OOMKilled — false. Строка в journalctl -k есть всегда.
Ты остановил контейнер командой 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в журнале ядра.