← К программе курса

Модуль 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 задаёт их частоту; успех во время start_period завершает льготный режим.

03

3. Теория: хорошая проверка

Probe должна быстро, дёшево и детерминированно проверять способность экземпляра обслужить запрос. Проверка лишь существования процесса даёт мало информации; глубокий запрос к каждой внешней зависимости создаёт каскадные отказы.

Healthcheck не является Kubernetes readiness/liveness-разделением. При необходимости traffic readiness реализует proxy/orchestrator, а приложение должно иметь retry, backoff и graceful degradation.

04

4. Теория: depends_on

Короткий depends_on ждёт только запуска dependency. condition: service_healthy ждёт healthy; service_completed_successfully подходит для конечной migration/job. Compose создаёт и удаляет services в dependency order.

Это startup coordination, а не runtime supervision. Если dependency позже отказала, приложение не обязано остановиться. restart: true внутри long-form depends_on относится к явной Compose-операции над dependency, не к автоматическому 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 лечат причиной, лимитом attempts и backoff приложения, а не бесконечным перезапуском.

06

6. Теория: границы и failure modes

Startup order не гарантирует готовность навсегда, а healthy не гарантирует корректность всех бизнес-операций. Клиенты должны переживать reconnect и временную недоступность.

Не соединяйте Docker restart policy с конкурирующим host process manager. Не используйте probe, которая меняет данные, требует привилегий или выводит secret.

07

7. Методические указания

  • Сначала определите проверяемое свойство
  • Назначьте timeout меньше interval
  • Оставьте запас retries для transient failure
  • Используйте start_period только для реального bootstrap
  • Храните output probe коротким и без secrets
  • Проверяйте State, Health.Log и events вместе
  • Не путайте restart counter с health failures
  • Тестируйте recovery, а не только failure
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 и докажите, что процесс не перезапущен, затем восстановите 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, failure приложения и failure 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 — effective command и timers
  • State.Health.Log — exit code, duration и output
  • State.ExitCode/OOMKilled/Error — причина завершения PID 1
  • RestartCount и events — фактические рестарты
  • Compose logs — порядок зависимостей
  • ручной запуск probe — только после сохранения evidence
10

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

  • Почему running не означает ready?
  • Как работает start_period?
  • Перезапускает ли 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.