Health Check для докер-контейнера

С версии докера 1.12 в докер-контейнере появилась возможность проверки работоспособности контейнера – так называемый health check. 

Типичный health check организуется периодическим вызовом некой команды, которая проверяет «жив» ли сервис, который исполняется в контейнере. Так, для веб-сервера который отвечает за работу некоторого сайта это может быть команда curl которая проверяет переделённую страницу веб-сайта, это может быть оценка используемой памяти сервисом или загрузка процессора в течении некоторого времени.

Статус «здоровья» докер-контейнера до первой проверки принимает значение “starting”. После любой успешной проверки он становится “healthy”. Если тест «падает» несколько раз подряд в течении определенного интервала, то такой контейнер считается «плохим» (unhealthy). Статус докер-контейнера можно проверить командами “docker ps” и “docker container ls”.

Если тексту с картинками вы предпочитаете видео, то вот мой обзор healthcheck для docker container на YouTube.


Как включить health check для докер-контейнера

Health check для докер-контейнера может быть указан в нескольких местах

  1. В командах “docker run” и “docker container run”
  2. В файле Dockerfile
  3. В файле Docker compose
  4. В команде docker service create

Рассмотрим установку health check на примере Dockerfile. Для Dockerfile она имеет вот такой формат. Вот здесь можно посмотреть спецификацию команды helalthcheck для dockerfile 

            HEALTHCHECK [OPTIONS] CMD command
  • OPTIONS – параметры проверки «здоровья» докер-контейнера. Их можно не указывать, если вас устраивают дефолтные параметры.
  • command – непосредственно команда из оболочки (shell) которая проверяет состояние докер-контейнера.
Например, она может выглядеть так. 

        HEALTHCHECK --interval=30s --timeout=1s --retries=3 --start-period=10s CMD curl --fail http://localhost:80/ping.html || exit 1
  • interval – указывает как часто надо проверять состояние докер-контейнера. По умолчанию - 30 секунд
  • timeout – если выполнение команды занимает больше времени чем указано в этом параметра, то он считается не успешным. По умолчанию - 30 секунд.
  • retries  -  число не успешных проверок выполненных подряд, после чего докер-контейнер считается «плохим» (unhealthy). По умолчанию - 3  попытки.
  • start-period – время, которое дается контейнеру на первоначальную загрузку.. По умолчанию - 0 секунд

Пример. Простейщий dockerfile с healthcheck
FROM nginx
RUN echo "ping" >> /usr/share/nginx/html/ping.html
HEALTHCHECK --interval=30s --timeout=10s --retries=5 --start-period=10s \
 CMD curl --fail http://localhost:80/ping.html || exit 1

Собираем образ командой 
docker image build  -t testhl .

и запускаем докер-контейнер
docker run --rm -d -p 80:80 testhl


Страница ping.html статическая, генерируется при сборке докер-образа, так что health check исправно определяется как “healthy”.

Меняем health check чтобы он выдавал ошибку, пересобираем докер-образ и запускаем докер-контейнер заново.

FROM nginx
RUN echo "ping" >> /usr/share/nginx/html/ping.html
HEALTHCHECK --interval=30s --timeout=10s --retries=5 --start-period=10s \
    CMD curl --fail http://localhost:80/ping2.html || exit 1

 
Страницы ping2.html в моем веб-сайте нет, так что health check через некоторое время определяется как unhealthy.

Автоматический перезапуск «проблемного» докер-контейнера

От одного понимания, что контейнер «испортился» пользы не много. Гораздо удобнее, было бы если докер мог бы перезапустить «проблемный» контейнер. К сожалению, «из коробки» такое работает только в режиме Docker Swarm, когда вы управляете кластером из докер-контейнеров. Более подробно про Swarm можно почитать https://docs.docker.com/engine/swarm/key-concepts/ 

Чтобы добиться такого же и для одного докер-контейнера нужно сделать следующее. 
  1. Заменить exit 1 на kill 1 в инструкции HEALTHCHECK
  2. Запускать докер-контейнер с опцией –restart always

Пример
  1. Меняем Dockerfile следующим образом
FROM nginx
RUN echo "ping" >> /usr/share/nginx/html/ping.html
HEALTHCHECK --interval=30s --timeout=10s --retries=5 --start-period=10s \
    CMD curl --fail http://localhost:80/ping2.html || kill 1

    2. Собираем новый имидж
    3. Запускаем имидж вот такой командой.
        docker container run --restart always -d -p 80:80 testhl

Обратите внимание, мне пришлось убрать опцию “--rm” так как она конфликтует с “--restart”

Обратите внимание на значения в поле STATUS. Я его проверял в разные интервалы времени и видно, что контейнер некоторое время работал (статус был up 5  seconds, up 22 seconds) и затем был перезапущен (статус стал up 11 seconds).

Комментарии

Популярные сообщения из этого блога

Команды docker save/load, docker export/import – в чем отличие, как и когда ими пользоваться

Как узнать, кто заблокировал файл или папку

Эрик Гамма переходит на работу в Майкрософт