Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Чому контейнер не завершується коректно при docker stop і до чого тут PID 1?

docker stop надсилає головному процесу контейнера (PID 1) сигнал SIGTERM і чекає (за замовчуванням 10 секунд). Якщо процес не завершився - надсилає SIGKILL, який не можна перехопити: усе обривається на півдорозі.

Чому SIGTERM не доходить до застосунку:

  1. Shell-форма команди. CMD php artisan queue:work запускається як /bin/sh -c "...". PID 1 - оболонка, а sh не передає сигнали дочірнім процесам. Воркер не дізнається, що треба зупинитися.
  2. Скрипт-обгортка без exec. entrypoint.sh, що просто викликає php-fpm в кінці, лишається PID 1, а FPM - його дочірнім процесом.
  3. PID 1 особливий у ядрі: для нього сигнали без явно встановленого обробника ігноруються. Процес, що не обробляє SIGTERM, ставши PID 1, не завершиться від нього.

Рішення:

CMD ["php", "artisan", "queue:work"]   # exec-форма: процес - PID 1
#!/bin/sh
# entrypoint.sh
php artisan config:cache
exec "$@"            # замінити оболонку командою, а не запустити дочірній процес
  • --init (init: true у Compose) додає крихітний init-процес (tini) як PID 1: він пересилає сигнали й прибирає процеси-зомбі.
  • stop_grace_period - більше часу, якщо коректне завершення справді довге.

Навіщо це на практиці: воркер черги, що отримав SIGTERM, доробляє поточне завдання й завершується. Убитий SIGKILL - обриває його посередині: напівзапис у базу, повторне виконання після рестарту. Тому --timeout воркера, stop_grace_period і ліміти оркестратора налаштовують узгоджено. Те саме для PHP-FPM (SIGQUIT - м'яке завершення) і Octane.

Докладніше в документації: Shell- і exec-форма в Dockerfile

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання