martes, 28 de enero de 2025

Healthcheck en Docker: ¿Qué es y cómo funciona?

Healthcheck en Docker: ¿Qué es y cómo funciona ?

Un healthcheck en Docker permite definir un mecanismo para que Docker supervise el estado de un contenedor. Esto se utiliza para determinar si una aplicación que se ejecuta dentro de un contenedor sigue funcionando correctamente. Si la comprobación de salud falla, Docker puede tomar medidas, como reiniciar el contenedor o marcarlo como no saludable.


Cómo funcionan los Healthchecks

  • Docker ejecuta un comando específico dentro del contenedor a intervalos regulares.

  • El comando debe devolver un estado:

    • 0: El contenedor está saludable.

    • 1: El contenedor no está saludable.

    • 2: El contenedor está en un estado inicial o indeterminado.

  • Los resultados se almacenan en el estado del contenedor (healthy, unhealthy, o starting).


Sintaxis en Dockerfile

En un archivo Dockerfile, puedes definir un healthcheck con la instrucción HEALTHCHECK:

HEALTHCHECK --interval=30s --timeout=10s --retries=3 CMD curl -f http://localhost:8080/health || exit 1

Opciones disponibles:

  • --interval=30s: Tiempo entre comprobaciones de salud (por defecto, 30 segundos).

  • --timeout=10s: Tiempo máximo que puede tardar el comando en ejecutarse (por defecto, 30 segundos).

  • --start-period=5s: Tiempo de gracia antes de realizar la primera comprobación (por defecto, 0).

  • --retries=3: Número de intentos antes de marcar el contenedor como unhealthy (por defecto, 3).

  • CMD: Comando que se ejecutará para realizar la comprobación.


Ejemplo básico

Dockerfile

FROM nginx:alpine

# Copia archivos necesarios (si aplica)
COPY ./index.html /usr/share/nginx/html/index.html

# Healthcheck para verificar que el servidor responde correctamente
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
   CMD curl -f http://localhost:80 || exit 1

CMD ["nginx", "-g", "daemon off;"]

En este ejemplo:

  • El comando curl -f http://localhost:80 verifica que el servidor NGINX esté respondiendo.

  • Si no responde correctamente, el contenedor se marcará como unhealthy.

Construir y ejecutar

docker build -t nginx-healthcheck .
docker run -d --name my-nginx nginx-healthcheck

Ver el estado de salud del contenedor

docker ps

La columna STATUS mostrará algo como:

  • healthy (si el healthcheck pasa).

  • unhealthy (si el healthcheck falla).

  • starting (si está en el período de inicio).


Healthcheck en docker-compose.yml

También puedes definir un healthcheck en un archivo docker-compose.yml:

version: "3.8"

services:
web:
  image: nginx:alpine
  healthcheck:
    test: ["CMD", "curl", "-f", "http://localhost:80"]
    interval: 30s
    timeout: 5s
    retries: 3
  ports:
    - "8080:80"

Ejecutar con Docker Compose

docker-compose up -d

Consulta el estado del contenedor con:

docker ps

Ver detalles del estado de salud

Para inspeccionar el estado de salud de un contenedor:

docker inspect <container_id>

Busca la sección State.Health en la salida:

"Health": {
   "Status": "healthy",
   "FailingStreak": 0,
   "Log": [
      {
           "Start": "2025-01-28T12:00:00.123456789Z",
           "End": "2025-01-28T12:00:01.123456789Z",
           "ExitCode": 0,
           "Output": ""
      }
  ]
}
  • Status: Puede ser healthy, unhealthy, o starting.

  • FailingStreak: Número de comprobaciones fallidas consecutivas.

  • Log: Historial de las comprobaciones de salud.


Ejemplo avanzado con scripts

Si necesitas una comprobación más compleja, puedes usar un script:

Dockerfile

FROM python:3.9-slim

# Copia el script de healthcheck
COPY healthcheck.sh /usr/local/bin/healthcheck.sh
RUN chmod +x /usr/local/bin/healthcheck.sh

# Healthcheck
HEALTHCHECK --interval=10s --timeout=5s --retries=3 CMD ["healthcheck.sh"]

CMD ["python", "-m", "http.server", "8080"]

healthcheck.sh

#!/bin/bash

# Verificar si el servidor responde en el puerto 8080
if curl -sf http://localhost:8080 > /dev/null; then
   exit 0
else
   exit 1
fi

Qué sucede si un contenedor es unhealthy

Cuando un contenedor se marca como unhealthy, Docker no lo reinicia automáticamente (a menos que uses una política de reinicio como --restart always).

Si necesitas que Docker lo gestione automáticamente, puedes usar un orquestador como Docker Swarm o Kubernetes, o configurar un script externo para monitorear el estado.