Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «У чому різниця між docker stop та docker kill?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`docker stop`** graceful: SIGTERM, чекає 10 секунд, поки застосунок завершиться, потім SIGKILL, якщо ще running. **`docker kill`** негайний: SIGKILL одразу (або сигнал, що задаси через `--signal`). ```bash docker stop web # SIGTERM, тоді SIGKILL через 10с docker stop -t 30 web # 30-секундне grace-вікно docker kill web # SIGKILL негайно docker kill --signal=SIGUSR1 web # надіслати кастомний сигнал ``` **Головне:** бери `stop` для graceful shutdown (бази, сервіси, що мають flush). Бери `kill` для зависнутих процесів, що ігнорують SIGTERM, або для надсилання довільних сигналів running-застосункам.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**`docker stop` і `docker kill`** обидва способи зупинити running container, але відрізняються за агресивністю. Вибір між ними переважно про те, чи застосунку всередині потрібен час на чисту зупинку. ## Теорія ### TL;DR - `docker stop` = **graceful**. Шле SIGTERM, чекає N секунд (дефолт 10), шле SIGKILL, якщо ще running. - `docker kill` = **негайний**. Шле SIGKILL за замовчуванням, або будь-який сигнал через `--signal`. - Обидва врешті змушують container вийти. Різниця в тому, чи отримує застосунок шанс прибрати. - Для баз, сервісів зі станом, чого-небудь з відкритими з'єднаннями, бери `stop`. - Для зависнутих процесів, застосунків з unresponsive PID 1, debug, `kill`. - `docker rm -f` = `docker kill` + `docker rm` в одному кроці. ### Що робить `docker stop` ``` t=0 daemon шле SIGTERM на PID 1 всередині container t=0..N застосунок має обробити SIGTERM: - закінчити in-flight запити - flush логів / WAL / кешу - закрити DB-з'єднання - чисто вийти з кодом 0 t=N якщо ще running, daemon шле SIGKILL (де N = --time, дефолт 10 секунд) ``` Grace-період налаштовується per stop: ```bash docker stop -t 30 mycontainer # 30 секунд docker stop -t 0 mycontainer # 0 = SIGKILL негайно (як kill) ``` Або per container при run: ```bash docker run --stop-timeout 60 myapp ``` ### Що робить `docker kill` ```bash docker kill <name> # SIGKILL за замовчуванням docker kill --signal=SIGTERM <name> # явний SIGTERM (без grace-вікна) docker kill --signal=SIGUSR1 <name> # будь-який сигнал docker kill -s 9 <name> # числовий сигнал ``` Флаг `--signal` робить `docker kill` гнучкішим, ніж його ім'я підказує. Це також спосіб надіслати non-fatal сигнал running-застосунку, наприклад, сказати nginx перечитати config: ```bash docker kill --signal=SIGHUP nginx-container # nginx перечитує config без рестарту. ``` Незважаючи на ім'я, `kill` не завжди вбиває, лише SIGKILL і SIGTERM (без trap) завершують процес. ### Side-by-side | | `docker stop` | `docker kill` | |---|---|---| | Дефолтний сигнал | SIGTERM, потім SIGKILL | SIGKILL | | Grace-період | так (дефолт 10с, налаштовується) | жодного | | Кастомний сигнал | ні | так (`--signal`) | | Для чистого shutdown | ТАК | ні | | Для зависнутих процесів | ні | ТАК | | Для надсилання сигналів (HUP, USR1) | ні | ТАК | ### Чому graceful важить ```bash # Postgres з --memory тиском у фоні docker stop pg # SIGTERM → postgres flush WAL, закриває з'єднання, exit 0 → усе ок docker kill pg # SIGKILL → postgres помирає мід-write → на наступному старті WAL-replay → потенційно повільне recovery ``` Для баз: stop, ніколи не kill (якщо не свідомо). ```bash # Web-сервіс з in-flight запитами docker stop api # SIGTERM → api припиняє приймати нові, добиває існуючі, exit → без client-помилок docker kill api # SIGKILL → з'єднання падають мід-flight → 502 для юзера ``` Для user-facing сервісів: stop. Завжди. ### Коли `kill` правильний - **Зависнутий процес**, що ігнорує SIGTERM і блокує усе. Stop чекав; kill закінчує. - **Надсилання control-сигналів** як SIGHUP (reload), SIGUSR1 (rotate logs), SIGUSR2 (debug dump) running-застосунку. - **Тести / disposable container**, де graceful shutdown не важить. - **`docker rm -f`** використовує kill внутрішньо, нормально для cleanup уже-зупинених або таких, що не важили, container. ### Типові помилки **Вбивати базу мід-write** ```bash # НЕПРАВИЛЬНО docker kill postgres-prod # Іноді recovers нормально; іноді корумповані індекси; іноді WAL-replay 30 хвилин. ``` Бери `docker stop`. Ще краще: спочатку чисто зупини застосунок, потім зупини container. **Застосунок ігнорує SIGTERM, тоді отримує SIGKILL через 10с** ```bash $ docker stop web # Виглядає повільно; бере усі 10 секунд; container виходить з 137. ``` Застосунок не обробляє SIGTERM = брудний shutdown після grace-періоду. Фікс застосунку: trap SIGTERM і виходь чисто. Тестуй через `docker stop` і підтверджуй exit 0 (або який чистий код) за пару секунд. **Брати `kill` для `--signal=SIGTERM` замість просто `stop`** ```bash # Те саме, що docker stop -t 0 (без grace-вікна) docker kill --signal=SIGTERM web ``` Це шле SIGTERM, але НЕ супроводжує SIGKILL'ом після grace-періоду, якщо застосунок ігнорує сигнал, container лишається running. Зазвичай хочеш `docker stop`, що ДОДАЄ SIGKILL. **Забути, що PID 1 має особливу signal-семантику** Linux PID 1 ігнорує більшість сигналів за замовчуванням, поки процес явно їх не обробляє. Якщо твій застосунок це PID 1 (так, у container), маєш trap SIGTERM у коді: ```js // Node.js приклад process.on('SIGTERM', () => { server.close(() => process.exit(0)); }); ``` Без цього trap `docker stop` чекає повний grace-період і шле SIGKILL. ### Реальне застосування - **Прод-деплої:** `docker stop` (або еквівалент stack-level оркестратора) для graceful shutdown. - **CI cleanup:** `docker rm -f $(docker ps -aq)` (kill + rm) для тестів, де graceful не важить. - **Reload config nginx:** `docker kill --signal=SIGHUP nginx`. - **Ротація логів:** `docker kill --signal=USR1 myapp`, щоб застосунок reopen log-файли. - **Hung-container debug:** `docker kill` після того, як `docker stop` чекав повний grace-період безуспішно. ### Питання для поглиблення **Q:** Який дефолтний grace-період і як його змінити? **A:** 10 секунд. Override per-stop через `docker stop -t N`, per-container через `docker run --stop-timeout N`, або у Compose через `stop_grace_period: 30s`. **Q:** Чи daemon retry'їть SIGTERM протягом grace-періоду? **A:** Ні. SIGTERM шлеться раз. Якщо застосунок його ігнорує, daemon чекає і потім SIGKILL. **Q:** Що означають exit code 137 vs 143? **A:** 137 = 128 + 9 (SIGKILL). 143 = 128 + 15 (SIGTERM). Container вийшов через відповідний сигнал. Якщо `docker stop` і бачиш 137, застосунок не обробив SIGTERM і його SIGKILL'нули після grace-періоду. **Q:** Чи можу надіслати сигнал, що running-процес отримає? **A:** Так, `docker kill --signal=<SIG> <container>` шле сигнал на PID 1 всередині. Чи робить застосунок з ним щось, залежить від коду застосунку (signal-handlers). **Q:** (Senior) Як забезпечити, що твій dockerized застосунок правильно обробляє SIGTERM? **A:** Три перевірки. (1) Код: встанови signal-handlers у entrypoint застосунку, що trap SIGTERM і починають graceful shutdown. (2) Init: уникай обгортання у shell-форму `/bin/sh -c`, це робить `sh` PID 1 і твій застосунок дитиною, що не отримує сигнал напряму. Бери exec-форму (`CMD ["node", "server.js"]`) або `tini` через `--init`. (3) Тестуй: `docker stop` свого container і assert, що він виходить за ~1 секунду з кодом 0 (або твоїм designated-чистим кодом), не після повного grace-періоду. ## Приклади ### Graceful-stop з продовженим grace-періодом ```bash # Прод-DB потребує час на flush $ docker stop -t 60 postgres-prod postgres-prod # Postgres обробляє SIGTERM, крутить checkpoint, виходить чисто. Зайняло ~12 секунд. ``` Довгий graceful-shutdown для stateful-сервісу. Швидше, ніж дозволив би дефолтний 10с timeout. ### Reload nginx-config без рестарту ```bash $ docker kill --signal=SIGHUP nginx-prod nginx-prod # nginx отримує HUP, перечитує config з /etc/nginx/nginx.conf, продовжує крутитися. # Усі існуючі з'єднання продовжуються без переривань. ``` Класичне використання `docker kill` для надсилання non-fatal control-сигналу. ### Діагностика зависнутого container ```bash # Застосунок ні на що не реагує $ docker stop -t 5 hung-container # Чекає 5с, шле SIGKILL. # Або скіпни чекання повністю: $ docker kill hung-container ``` Для container, що застряг, kill правильний tool, graceful марне чекання. ### Compose grace-period налаштування ```yaml services: api: image: myapp stop_grace_period: 30s # docker compose stop чекатиме до 30с stop_signal: SIGUSR1 # бери SIGUSR1 замість SIGTERM (рідко) ``` Compose дозволяє кастомізувати per service. Для більшості застосунків дефолт нормально; для slow-shutting-down DB або worker подовжуй.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.