← До програми курсу

Модуль 11 / 18

Healthcheck, залежності та restart policies

DOCKER

Зміст
01

1. Цілі та модель готовності

Після модуля ви зможете розрізняти running, healthy і ready, проєктувати probes, керувати startup dependencies та обирати restart policy.

  • running означає лише існування PID 1
  • healthcheck виконується всередині container
  • unhealthy сам не перезапускає container
  • depends_on задає порядок та умови
  • restart policy реагує на завершення процесу
02

2. Теорія: HEALTHCHECK

Контейнер із healthcheck проходить starting → healthy або unhealthy. Exit 0 означає успіх, 1 — відмову, 2 зарезервований. Engine зберігає короткий output останніх перевірок і створює health_status events.

interval задає період, timeout обмежує probe, retries рахує послідовні відмови. start_period не враховує ранні failures, start_interval задає їх частоту; успіх завершує пільговий режим.

03

3. Теорія: якісна перевірка

Probe має швидко, дешево й детерміновано перевіряти здатність екземпляра обслуговувати запит. Лише існування процесу дає мало інформації, а глибока перевірка всіх dependencies створює каскадні відмови.

Healthcheck не розділяє Kubernetes readiness/liveness. Застосунок усе одно потребує retry, backoff та graceful degradation.

04

4. Теорія: depends_on

Короткий depends_on чекає лише запуск dependency. service_healthy чекає healthy; service_completed_successfully підходить для migration/job. Compose створює та видаляє services у dependency order.

Це startup coordination, а не runtime supervision. restart: true у long-form depends_on стосується явної Compose-операції, а не автоматичного Engine restart.

05

5. Теорія: restart policies

no не перезапускає; on-failure[:N] реагує на non-zero exit; always і unless-stopped переживають daemon restart з різницею після ручної зупинки. Моніторинг починається після успішного запуску близько 10 секунд.

Unhealthy не завершує PID 1 і тому не активує restart policy. Restart loop усувають через root cause, обмеження attempts і backoff.

06

6. Теорія: межі та failure modes

Startup order не гарантує постійну готовність, а healthy не гарантує всі business operations. Клієнти мають переживати reconnect.

Не поєднуйте Docker restart policy з конкуруючим host process manager. Probe не має змінювати дані, вимагати privileges чи виводити secret.

07

7. Методичні вказівки

  • Спочатку визначте властивість для перевірки
  • Timeout має бути меншим за interval
  • Залиште retries для transient failure
  • Start_period лише для реального bootstrap
  • Output без secrets
  • Перевіряйте State, Health.Log та events
  • Не плутайте restart counter з health failures
  • Тестуйте recovery
08

8. Лабораторна робота

Створіть повільний gate, успішну migration та залежний застосунок. --wait має завершитися після виконання умов.

terminal
mkdir -p /tmp/docker-module-11
printf '%s\n' 'name: docker-m11' 'services:' '  gate:' '    image: alpine:3.21' '    command: ["sh", "-c", "rm -f /tmp/ready; sleep 4; touch /tmp/ready; sleep 300"]' '    healthcheck:' '      test: ["CMD", "test", "-f", "/tmp/ready"]' '      interval: 1s' '      timeout: 1s' '      retries: 5' '      start_period: 2s' '      start_interval: 500ms' '    restart: unless-stopped' '  migrate:' '    image: alpine:3.21' '    command: ["sh", "-c", "echo migration=complete"]' '  app:' '    image: alpine:3.21' '    command: ["sh", "-c", "date -u +app_started=%FT%TZ; sleep 300"]' '    depends_on:' '      gate:' '        condition: service_healthy' '      migrate:' '        condition: service_completed_successfully' > /tmp/docker-module-11/compose.yaml
cd /tmp/docker-module-11
docker compose config --quiet
docker compose up --detach --wait --wait-timeout 30
docker compose ps --all
docker compose logs --no-color gate migrate app
terminal
cd /tmp/docker-module-11
docker inspect docker-m11-gate-1 --format 'state={{.State.Status}} health={{.State.Health.Status}} restarts={{.RestartCount}}'
docker inspect docker-m11-gate-1 --format '{{json .State.Health.Log}}' | jq '.[-3:] | map({Start,End,ExitCode,Output})'
docker events --since 10m --until 0s --filter container=docker-m11-gate-1 --filter event=health_status

Зробіть gate unhealthy без restart, потім відновіть ready state.

terminal
cd /tmp/docker-module-11
docker compose exec --interactive=false gate rm /tmp/ready
sleep 6
docker inspect docker-m11-gate-1 --format 'state={{.State.Status}} health={{.State.Health.Status}} restarts={{.RestartCount}}'
docker compose exec --interactive=false gate touch /tmp/ready
sleep 2
docker inspect docker-m11-gate-1 --format 'state={{.State.Status}} health={{.State.Health.Status}} restarts={{.RestartCount}}'

Окремо перевірте обмежений on-failure restart.

terminal
docker run --detach --name docker-m11-restart --restart on-failure:2 alpine:3.21 sh -c 'n=0; test -f /attempt && n=$(cat /attempt); n=$((n+1)); echo "$n" > /attempt; echo attempt=$n; test "$n" -ge 3 && sleep 300; exit 1'
sleep 6
docker inspect docker-m11-restart --format 'state={{.State.Status}} exit={{.State.ExitCode}} restarts={{.RestartCount}}'
docker logs docker-m11-restart
docker update --restart no docker-m11-restart

Критерій: app стартує після healthy та migration; unhealthy має RestartCount 0; restart-demo доходить до третьої спроби.

09

9. Діагностика starting, unhealthy та restart loop

Розділяйте failure probe, застосунку та runtime.

terminal
cd /tmp/docker-module-11
docker compose ps --all
docker inspect docker-m11-gate-1 --format '{{json .State}}' | jq
docker inspect docker-m11-gate-1 --format '{{json .Config.Healthcheck}}' | jq
docker compose logs --no-color --timestamps --tail 50
docker events --since 10m --until 0s --filter type=container | tail -30
  • Config.Healthcheck — command і timers
  • State.Health.Log — exit, duration та output
  • State.ExitCode/OOMKilled/Error — завершення PID 1
  • RestartCount та events — рестарти
  • Compose logs — порядок dependencies
  • ручний probe — після evidence
10

10. Контроль і cleanup

  • Чому running не ready?
  • Як працює start_period?
  • Чи restart робить unhealthy?
  • service_started чи service_healthy?
  • Коли service_completed_successfully?
  • always чи unless-stopped?
  • Чим небезпечний restart loop?
  • Що містить Health.Log?
terminal
docker rm --force docker-m11-restart 2>/dev/null || true
cd /tmp/docker-module-11
docker compose down --remove-orphans
cd /
rm -f /tmp/docker-module-11/compose.yaml
rmdir /tmp/docker-module-11
docker ps -a --filter name=docker-m11

Модуль засвоєно, якщо ви доводите готовність фактами й відрізняєте startup dependency від runtime recovery.