В этом материале
Когда docker stop ждёт до принудительного завершения, исследуйте дерево процессов и PID 1. Shell-wrapper может не передавать сигнал worker, а основной процесс — не обрабатывать TERM. Дополнительная проблема возникает, если никто не собирает завершившиеся дочерние процессы.
Когда docker stop ждёт до принудительного завершения, исследуйте дерево процессов и PID 1. Shell-wrapper может не передавать сигнал worker, а основной процесс — не обрабатывать TERM. Дополнительная проблема возникает, если никто не собирает завершившиеся дочерние процессы.
Восстановите команду запуска
Сохраните image ENTRYPOINT, CMD и фактически запущенные аргументы. Установите, какая программа стала PID 1 внутри контейнера и кто является родителем worker. Интерактивный shell и production entrypoint могут создавать разные деревья. Для shell-script, запускающего единственный основной процесс, exec меняет модель: программа заменяет shell вместо запуска отдельным потомком. Однако корректность зависит от самого приложения и его обработки сигналов, а не только от формы Dockerfile.
Разделите доставку сигнала и cleanup
Docker направляет stop signal основному процессу. PID 1 имеет особое поведение обработки сигналов Linux; приложение должно реализовать нужное завершение. Передача TERM дочернему worker и reaping завершившихся детей — отдельные обязанности. —init добавляет небольшой init-процесс для соответствующих функций, но не придумывает за приложение протокол сохранения данных. Наличие init не подтверждает автоматически, что каждый worker получил сигнал и освободил свой ресурс.
Проверьте условный wrapper
В учебном сценарии script запускает worker в фоне и остаётся ждать. После stop лог содержит только завершение shell, а worker не записывает свой финальный маркер. Сравните это с вариантом корректного exec или явного trap/forwarding, подобранным под реальное дерево. Затем создайте отдельный короткоживущий дочерний процесс и проверьте, исчезает ли он из zombie состояния. Пример не требует запускать реальную модель или менять CUDA настройки.
| Данные опыта | Проверяемое свойство |
|---|---|
| PID/PPID дерево | Определён получатель stop signal |
| Маркер TERM worker | Подтверждена обработка сигнала |
| Время завершения | Видно ожидание до принудительного stop |
| Завершившиеся дети | Проверена обязанность reaping |
Исправьте минимальный участок
Для одного основного приложения избегайте лишнего слоя shell, если он не нужен. Для нескольких процессов явно определите supervision и порядок остановки. Сохраните ограниченное время ожидания, достаточное для предусмотренного cleanup. Увеличение stop timeout маскирует отсутствующий forwarding, если worker вообще не получает сигнал. Проверьте права на запись финального состояния: корректно доставленный TERM не помогает, когда завершающий обработчик сам блокируется или пытается писать в недоступный путь.
Проверьте несколько завершений
Повторите запуск и stop в состоянии простоя, во время работы и после отказа дочернего процесса. Сохраните ожидаемые exit codes и финальные маркеры без пользовательских данных. Итоговый артефакт содержит дерево, способ доставки сигнала, ответственного за reaping и предельное время завершения. Эти сведения понадобятся и при Kubernetes deployment, где grace period ограничивает весь процесс остановки. Прекращение существования объекта контейнера не должно быть единственным доказательством выполненного cleanup внутри приложения.
Связанные разборы: gpu containers vs vms; vllm docker first launch.