Що таке restart policy і які варіанти існують?
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 — дефолт
docker run myapp
# Crash → exited. Лишається exited.
# Host reboot → container не повертається.Нормально для одноразових команд (docker run --rm для CI-job). Неправильно для будь-якого сервісу, що має крутитися.
on-failure[:N] — рестарт на crash до N разів
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 — рестарт незважаючи ні на що
docker run --restart=always mysvc
# Crash, чистий exit, host reboot → daemon його повертає кожного разу.
# Навіть після `docker stop` daemon його рестартує.Назва буквальна: ЗАВЖДИ. Включно після ручного stop, щоб реально зупинити, маєш зробити docker rm. Дивує; зазвичай хочеш unless-stopped.
unless-stopped — прод-дефолт
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-синтаксис
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.
Типові помилки
Забути поставити політику на довгоживучий сервіс
# НЕПРАВИЛЬНО: дефолт "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 не тримається
$ docker run -d --name api --restart=always myapp
$ docker stop api
$ docker ps # api повернувсяalways буквально означає завжди. Бери unless-stopped, якщо хочеш, щоб ручний stop поважався.
Crash-loop без фільтра exit-коду
# 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-статусу.
# 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
$ 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
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, щоб запобігти нескінченних циклів
$ 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 # фінальний стан, без retryon-failure:N це safety-net для job, що можуть падати назавжди. Без cap daemon retry'їть нескінченно.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.
Коментарі
Ще немає коментарів