Skip to content

Instantly share code, notes, and snippets.

@radimih
Last active July 23, 2024 09:47
Show Gist options
  • Save radimih/93c5bf44374c6d3df68fa41401ec2bd5 to your computer and use it in GitHub Desktop.
Save radimih/93c5bf44374c6d3df68fa41401ec2bd5 to your computer and use it in GitHub Desktop.
Healthcheck Docker-образа Java-приложения

Docker healthcheck

Легковесная реализация Docker HEALTHCHECK без использования внешних утилит (curl, wget и тд.), когда требуется проверять результат HTTP-запроса к приложению. На примере проверки статуса Java-приложения с включенным модулем Spring Boot Actuator .

Если базовый образ основан на Alpine

Alpine использует программу BusyBox, которая реализует в том числе усечённую версию утилиты ncat (nc).

Общая часть Dockerfile:

FROM eclipse-temurin:21-jre-alpine

ENV TZ=Europe/Moscow
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \
    echo $TZ > /etc/timezone

RUN addgroup --system --gid 10001 appuser && \
    adduser  --system --uid 10001 --ingroup appuser --home /opt/app appuser

Варианты:

  • через формирование дополнительного shell-скрипта healthcheck.sh, в который "вшивается" номер порта на этапе сборки образа:

    <общая часть Dockerfile>
    
    ARG PORT=8080
    EXPOSE ${PORT}
    
    WORKDIR /opt/app
    
    RUN cat <<EOF > healthcheck.sh && chmod 555 healthcheck.sh
    #!/bin/sh
    echo -e "GET /actuator/health HTTP/1.1\r\nHost: localhost:${PORT}\r\n\r\n" \
     | nc -w1 localhost ${PORT} \
     | grep status | grep UP || exit 1
    EOF
    
    HEALTHCHECK --start-period=30s --interval=10s --timeout=3s --retries=3 \
                CMD ["/opt/app/healthcheck.sh"]
    ...
  • через использование переменной окружения PORT времени выполнения контейнера:

    <общая часть Dockerfile>
    
    ARG PORT=8080
    ENV PORT=${PORT}
    EXPOSE ${PORT}
    
    HEALTHCHECK --start-period=30s --interval=10s --timeout=3s --retries=3 \
                CMD echo -e "GET /actuator/health HTTP/1.1\r\nHost: localhost:${PORT}\r\n\r\n" \
                    | nc -w1 localhost ${PORT} \
                    | grep status | grep UP || exit 1
    ...
  • максимально быстрый вариант, но номер порта необходимо прописывать в нескольких местах:

    <общая часть Dockerfile>
    
    EXPOSE 8080
    
    HEALTHCHECK --start-period=30s --interval=10s --timeout=3s --retries=3 \
                CMD echo -e "GET /actuator/health HTTP/1.1\r\nHost: localhost:8080\r\n\r\n" \
                    | nc -w1 localhost 8080 \
                    | grep status | grep UP || exit 1
    ...

Если базовый образ включает в себя bash

Используется возможность в оболочке bash работать напрямую с TCP-сокетами:

Общая часть Dockerfile:

FROM eclipse-temurin:21-jre-noble  # Ubuntu 24.04

ENV TZ=Europe/Moscow
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \
    echo $TZ > /etc/timezone

RUN useradd --system --uid 10001 --user-group --home-dir /opt/app --create-home appuser

Варианты:

  • через формирование дополнительного shell-скрипта healthcheck.sh, в который "вшивается" номер порта на этапе сборки образа:

    <общая часть Dockerfile>
    
    ARG PORT=8080
    EXPOSE ${PORT}
    
    WORKDIR /opt/app
    
    RUN cat <<EOF > healthcheck.sh && chmod 555 healthcheck.sh
    #!/bin/bash
    exec 3<>/dev/tcp/localhost/${PORT}
    echo -e "GET /actuator/health HTTP/1.1\r\nHost: localhost:${PORT}\r\n\r\n" >&3
    timeout 1 cat <&3 | grep status | grep UP || exit 1
    EOF
    
    HEALTHCHECK --start-period=30s --interval=10s --timeout=3s --retries=3 \
                CMD ["/opt/app/healthcheck.sh"]
    ...
  • через использование переменной окружения PORT времени выполнения контейнера:

    <общая часть Dockerfile>
    
    ARG PORT=8080
    ENV PORT=${PORT}
    EXPOSE ${PORT}
    
    HEALTHCHECK --start-period=30s --interval=10s --timeout=3s --retries=3 \
                CMD ["/usr/bin/bash", "-c", "exec 3<>/dev/tcp/localhost/${PORT}; \
                    echo -e \"GET /actuator/health HTTP/1.1\r\nHost: localhost:${PORT}\r\n\r\n\" >&3; \
                    timeout 1 cat <&3 | grep status | grep UP || exit 1"]
    ...
  • максимально быстрый вариант, но номер порта необходимо прописывать в нескольких местах:

    <общая часть Dockerfile>
    
    EXPOSE 8080
    
    HEALTHCHECK --start-period=30s --interval=10s --timeout=3s --retries=3 \
                CMD ["/usr/bin/bash", "-c", "exec 3<>/dev/tcp/localhost/8080; \
                    echo -e \"GET /actuator/health HTTP/1.1\r\nHost: localhost:8080\r\n\r\n\" >&3; \
                    timeout 1 cat <&3 | grep status | grep UP || exit 1"]
    ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment