Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке restart policy і які варіанти існують?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Docker restart policy** каже daemon, коли автоматично рестартувати exited container. Чотири опції: `no` (дефолт), `on-failure[:N]`, `always`, `unless-stopped`. ```bash docker run --restart=unless-stopped myapp # прод-дефолт docker run --restart=on-failure:5 myjob # спробувати до 5 разів docker run --restart=always mywebservice # завжди повертатися docker run myapp # дефолт: без рестарту ``` **Головне:** `unless-stopped` це прод-sweet spot, рестартує на crash і reboot host, але поважає твій ручний `docker stop`. `always` ігнорує і ручний stop. `no` дефолт, що неправильний для будь-якого довгоживучого сервісу.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Docker restart policy** автоматизує resilience container. Crash? Daemon рестартує. Host reboot? Container повертається. Чотири опції trade-off контроль vs автоматизація по-різному, обирай за тим, що хочеш, щоб container переживав. ## Теорія ### TL;DR - `--restart=<policy>` на `docker run` (або `restart: <policy>` у Compose) ставить політику. - **Чотири значення:** `no`, `on-failure[:N]`, `always`, `unless-stopped`. - **Прод-дефолт: `unless-stopped`**, переживає crash і host reboot, поважає ручний stop. - **Дефолт, якщо не вказано: `no`**, container виходить і лишається exited. - Restart-policy спрацьовує на **exit container**, незалежно від того, чи exit чистий (0) чи ні. Фільтр по коду це те, що додає `on-failure`. ### Чотири політики | Політика | На exit (будь-який код) | На exit код 0 | Після host-reboot | Поважає ручний stop | |---|---|---|---|---| | `no` (дефолт) | ні | ні | ні | n/a | | `on-failure[:N]` | так, якщо код != 0, до N разів | ні | ні (не переживає reboot) | так | | `always` | так | так | так | **ні** (рестартує навіть після stop) | | `unless-stopped` | так | так | так (якщо було running) | **так** | #### `no` — дефолт ```bash docker run myapp # Crash → exited. Лишається exited. # Host reboot → container не повертається. ``` Нормально для одноразових команд (`docker run --rm` для CI-job). Неправильно для будь-якого сервісу, що має крутитися. #### `on-failure[:N]` — рестарт на crash до N разів ```bash docker run --restart=on-failure myjob # необмежено retry на non-zero exit docker run --restart=on-failure:5 myjob # макс 5 retry ``` Бери для **batch-job**, що мають retry на transient failure, але врешті здаватися. Host-reboot їх не повертає (вони job, не service). #### `always` — рестарт незважаючи ні на що ```bash docker run --restart=always mysvc # Crash, чистий exit, host reboot → daemon його повертає кожного разу. # Навіть після `docker stop` daemon його рестартує. ``` Назва буквальна: ЗАВЖДИ. Включно після ручного stop, щоб реально зупинити, маєш зробити `docker rm`. Дивує; зазвичай хочеш `unless-stopped`. #### `unless-stopped` — прод-дефолт ```bash docker run --restart=unless-stopped mysvc # Crash → restart. Host reboot → restart. Ручний `docker stop` → ЛИШАЄТЬСЯ зупинений. ``` Правильна політика для 95% довгоживучих сервісів. Daemon рестартує на failure або reboot; поважає твій намір, коли ти зупиняєш вручну. ### Як взаємодіє з daemon - **На exit container:** daemon перевіряє політику і вирішує, чи рестартувати. - **На рестарт daemon (`systemctl restart docker`):** container з `always` і `unless-stopped` (що були running до рестарту) повертаються. `on-failure` НІ, він per-exit only. - **На host reboot:** те саме, що рестарт daemon. - Daemon використовує **експоненційний backoff** між retry: 100мс, 200мс, 400мс, ... до cap. Запобігає hot-loop crash-шторму. ### Compose-синтаксис ```yaml services: api: image: myapp restart: unless-stopped # найпоширеніше worker: image: myworker restart: on-failure # job-style oneoff: image: alpine command: echo hi restart: "no" # one-shot ``` Нота: `"no"` у YAML треба брати у лапки, інакше YAML парсить як boolean `false`. ### Типові помилки **Забути поставити політику на довгоживучий сервіс** ```bash # НЕПРАВИЛЬНО: дефолт "no"; container не переживає host reboot docker run -d --name api -p 80:80 myapp # ПРАВИЛЬНО docker run -d --name api -p 80:80 --restart=unless-stopped myapp ``` Це найпоширеніша operations-помилка на single-host деплоях. Container працює, ідеш додому, host рестартується вночі, сервіс down і телефон дзвонить. **Брати `always` і дивуватися, що ручний stop не тримається** ```bash $ docker run -d --name api --restart=always myapp $ docker stop api $ docker ps # api повернувся ``` `always` буквально означає завжди. Бери `unless-stopped`, якщо хочеш, щоб ручний stop поважався. **Crash-loop без фільтра exit-коду** ```bash # Container exit з кодом 0, але ти хочеш рестарт тільки на failure docker run --restart=always myjob # Рестартує вічно, навіть на чистих exit. Скоріш за все не те, що хочеш. # Краще: docker run --restart=on-failure myjob ``` **Забути, що `on-failure` не переживає reboot** Якщо container paused або running, коли ти reboot'аєш, on-failure його не повертає. Бери `unless-stopped`, якщо потрібне виживання reboot. ### Restart policy + healthcheck Docker restart-policy реагує на **exit процесу**, не на **unhealthy healthcheck**. Unhealthy container, що не вийшов, не рестартується Docker. Щоб діяти на healthcheck: - Swarm замінює unhealthy task новими (налаштовується). - Compose з `condition: service_healthy` лише gate'ує startup, не runtime-рестарт. - Звичайний Docker: external watchdog (autoheal-container, кастомний скрипт) може `docker restart` на основі health-статусу. ```bash # willfarrell/autoheal: моніторить і auto-restart unhealthy container docker run -d \ --name autoheal \ -v /var/run/docker.sock:/var/run/docker.sock \ -e AUTOHEAL_CONTAINER_LABEL=autoheal \ willfarrell/autoheal docker run -d --label=autoheal=true --health-cmd="..." myapp ``` ### Реальне застосування - **Прод single-host сервіси:** `unless-stopped` всюди, майже без винятків. - **CI / build container:** без restart-policy (дефолт `no`). Крутяться, виходять, лишаються exited. - **Background-worker:** `on-failure:N`, щоб transient-краши retry, а permanently-broken job урешті здавалося. - **Критична інфраструктура (host від нього залежить):** іноді `always` виправдане, наприклад, security-агент, що має бути up незважаючи на. ### Питання для поглиблення **Q:** Яка різниця між `always` і `unless-stopped`? **A:** `always` рестартує навіть після ручного `docker stop`. `unless-stopped` ні. Обидва переживають crash і host reboot; різниця в тому, чи поважається твій намір (`docker stop`). **Q:** Чи застосовується restart-policy, якщо я `docker rm` container? **A:** Ні, як видалено, нема чого рестартувати. Політики оперують на існуючих container. **Q:** Як побачити, яка політика у container? **A:** `docker inspect <name> --format '{{.HostConfig.RestartPolicy.Name}}'`. Повертає `always`, `unless-stopped`, `on-failure` або порожнє для `no`. **Q:** Чи `--restart` застосовується у Swarm-сервісі? **A:** Ні. Swarm-сервіси беруть `restart_policy:` у deploy-config (з `condition: any|on-failure|none`, `delay`, `max_attempts`). Флаг `--restart` для standalone-container. **Q:** (Senior) Коли НЕ варто використовувати restart-policy взагалі? **A:** Коли щось інше відповідальне за life-cycle container. K8s-pod керується kubelet, Docker restart-policy нерелевантна всередині K8s-pod (і ігнорується). Те саме для systemd-managed container через `docker run --rm` з unit. Правило: один restart-authority per container; обери оркестрацію, що володіє ним. ## Приклади ### Production-style сервіс з кількома шарами resilience ```bash $ docker run -d \ --name api \ --restart=unless-stopped \ -p 3000:3000 \ -v api_data:/data \ --health-cmd='curl -f http://localhost:3000/health || exit 1' \ --health-interval=30s \ --memory=512m \ myapp:1.0 ``` - Crash процесу → daemon рестартує через політику. - Host reboot → container повертається. - Ручний `docker stop` → лишається зупиненим (ти знаєш, що зробив). - Healthcheck робить статус видимим для моніторингу + reverse proxy. ### Compose: різні політики per service ```yaml services: api: image: myapp restart: unless-stopped worker: image: myworker restart: on-failure # batch retry migrator: image: mymigrator restart: "no" # one-shot, не рестартити profiles: [migrate] # opt-in profile ``` Різні форми роботи, різні політики. Migrator має крутитися раз і лишатися exited. ### Cap retry, щоб запобігти нескінченних циклів ```bash $ docker run -d --name flaky --restart=on-failure:3 myjob # Після 3 non-zero exit daemon припиняє пробувати. $ docker ps -a --filter name=flaky --format '{{.Status}}' Exited (1) 5 seconds ago # фінальний стан, без retry ``` `on-failure:N` це safety-net для job, що можуть падати назавжди. Без cap daemon retry'їть нескінченно.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.