Guía: health checks y readiness probes para aplicaciones PHP en Docker Swarm con dependencia de base de datos y caché — prácticas que funcionan
Por Kevin Marcondes · Publicado el · 9 min de lectura
Guía: health checks y readiness para aplicaciones PHP en Docker Swarm con dependencia de base de datos y caché. Verás cómo escribir un healthcheck profundo en PHP, orquestar dependencias desde el entrypoint e implementar readiness real mediante el proxy. Incluye ejemplos de stack.yml, scripts y criterios de tiempo para reducir 502 y loops de reinicio.
Salud vs readiness en Swarm: visión práctica
El health check verifica si el contenedor está operativo. La readiness indica si la instancia puede recibir tráfico sin errores. En Docker Swarm, el HEALTHCHECK no retira tareas del balanceo de la mesh, por lo que por sí solo no controla el tráfico.
El enfoque sólido para PHP con base de datos y caché incluye: un HEALTHCHECK profundo en PHP, un entrypoint que espera las dependencias y un proxy (Traefik/HAProxy) que valide un endpoint /ready. Los rolling updates con start-first y delays permiten que las réplicas nuevas se calienten.
Si usas Compose en el día a día, consulta el guía complementario sobre health checks en Docker Compose para PHP para entender qué se puede reaprovechar y qué cambia en Swarm.
- Health check: estado del contenedor (exit code).
- Readiness: apto para recibir tráfico sin errores por dependencias.
- Swarm no usa HEALTHCHECK para filtrar tráfico en la mesh.
- Usa proxy con chequeo HTTP para readiness.
- Usa update_config para actualizaciones graduales.
¿Cómo escribir un healthcheck en PHP que valide base de datos y caché?
Un healthcheck eficaz prueba las dependencias críticas. En PHP-FPM, ejecuta un script PHP por CLI que intente un SELECT 1 en Postgres (o MySQL) y un PING en Redis. Si un paso falla, devuelve estado 1. Configura intervalos cortos y start_period para evitar falsos negativos durante el arranque.
El ejemplo a continuación espera variables como DB_DSN, DB_USER, DB_PASS y REDIS_URL. Usa la extensión Redis si está disponible y hace fallback a TCP simple.
<?php
declare(strict_types=1);
function fail(string $msg): void {
fwrite(STDERR, $msg.PHP_EOL);
exit(1);
}
$errors = [];
$dbDsn = getenv('DB_DSN') ?: '';
$dbUser = getenv('DB_USER') ?: '';
$dbPass = getenv('DB_PASS') ?: '';
if ($dbDsn) {
try {
$pdo = new PDO($dbDsn, $dbUser, $dbPass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_TIMEOUT => 2,
]);
$pdo->query('SELECT 1');
} catch (Throwable $e) {
$errors[] = 'db';
}
}
$redisUrl = getenv('REDIS_URL') ?: '';
if ($redisUrl) {
$parts = parse_url($redisUrl);
$host = $parts['host'] ?? '127.0.0.1';
$port = (int)($parts['port'] ?? 6379);
$pass = $parts['pass'] ?? null;
try {
if (class_exists('Redis')) {
$r = new Redis();
$r->connect($host, $port, 1.5);
if ($pass) { $r->auth($pass); }
$r->ping();
} else {
$fp = @fsockopen($host, $port, $errno, $errstr, 1.5);
if (!$fp) { throw new RuntimeException('redis tcp failed'); }
fclose($fp);
}
} catch (Throwable $e) {
$errors[] = 'redis';
}
}
if ($errors) {
fail('Unhealthy: '.implode(',', $errors));
}
echo "OK\n";
Configurando el HEALTHCHECK y la stack de Swarm
Define el HEALTHCHECK en el Dockerfile y refiérelo en el servicio de la stack. Usa retries, interval y start_period compatibles con el tiempo de arranque y calentamiento de la aplicación. Un start_period demasiado corto provoca falsos negativos. En Swarm, combínalo con update_config para actualizaciones seguras.
El ejemplo muestra 3 réplicas, order start-first y rollback automático si se detectan fallos durante el monitoreo del update. Recuerda que el HEALTHCHECK por sí solo no controla la entrega de tráfico en la mesh.
version: "3.9"
services:
app:
image: registry.example.com/myapp:latest
env_file:
- app.env
healthcheck:
test: ["CMD", "php", "/app/.health/deep-healthcheck.php"]
interval: 10s
timeout: 3s
start_period: 20s
retries: 3
deploy:
replicas: 3
update_config:
parallelism: 1
order: start-first
delay: 10s
failure_action: rollback
monitor: 15s
restart_policy:
condition: any
max_attempts: 3
window: 30s
networks: ["frontend", "backend"]
web:
image: nginx:alpine
ports: ["80:80"]
networks: ["frontend", "backend"]
networks:
frontend:
driver: overlay
backend:
driver: overlay
¿Cómo implementar readiness de verdad en Swarm?
La readiness efectiva en Swarm depende de tu balanceador/proxy. Configura un endpoint HTTP /ready en la aplicación y haz que el proxy retire instancias que fallen en la comprobación. El HEALTHCHECK interno sigue siendo útil para diagnóstico, pero no controla el tráfico de la mesh.
Combina la readiness en el proxy con start-first y pequeños delays. Así la nueva task calienta caches y conexiones antes de recibir tráfico. Ve ejemplos prácticos de HAProxy con health checks y de enrutamiento gradual con canary usando Traefik.
| Mecanismo | ¿Garantiza readiness? | Dónde configurar | Observaciones |
|---|---|---|---|
| Docker HEALTHCHECK | No, en Swarm no filtra tráfico | Dockerfile/stack | Útil para diagnóstico y gates internos; la mesh ignora el estado |
| Health check en el proxy (HAProxy/Traefik) | Sí, retira réplicas malas del pool | Configuración del proxy | Chequea HTTP /ready; puede incluir verificación de DB/cache vía la app |
| Rolling update start-first + delay | Parcial | deploy.update_config | Calienta antes del switch; no valida salud de forma completa |
Orquestando dependencias con entrypoint "wait-for"
Como depends_on no garantiza readiness en Swarm, usa un entrypoint que espere a la base de datos y al cache antes de iniciar PHP-FPM. No bloquees indefinidamente: impón un timeout y falla con exit 1 para que el orquestador pruebe reiniciar.
El script abajo usa nc para chequear TCP. Adapta puertos y variables según tu entorno (por ejemplo: Postgres 5432, Redis 6379).
#!/usr/bin/env sh
set -e
wait_for_host() {
host="$1"; port="$2"; name="$3"; timeout="${4:-30}"
echo "Waiting for $name at $host:$port..."
for i in $(seq 1 "$timeout"); do
if nc -z "$host" "$port" >/dev/null 2>&1; then
echo "$name is up"; return 0
fi
sleep 1
done
echo "Timeout waiting for $name"; return 1
}
[ -n "$DB_HOST" ] && wait_for_host "$DB_HOST" "${DB_PORT:-5432}" "database"
[ -n "$REDIS_HOST" ] && wait_for_host "$REDIS_HOST" "${REDIS_PORT:-6379}" "redis"
exec php-fpm -F
Estrategias por dependencia: qué chequear en cada una
Cada dependencia requiere un tipo de verificación diferente. Evita comprobaciones costosas en producción. Prefiere operaciones ligeras e idempotentes. Agrupa señales en un endpoint /ready que devuelva 200 sólo cuando todo esté estable.
Para PHP-FPM, expón un endpoint interno ligero. Para DB y cache, valida conectividad y operaciones mínimas.
- PHP-FPM: endpoint HTTP ligero (por ejemplo /ready) que realice una operación simple de la aplicación.
- PostgreSQL/MySQL: SELECT 1 con timeout corto; evita correr migraciones en el healthcheck.
- Redis: PING y set/get de una clave efímera con TTL bajo.
- Colas (p. ej. RabbitMQ): conexión + declare de cola pasiva, sin consumir mensajes.
- Sistemas externos: HEAD/GET con timeouts y circuit breaker en la aplicación.
Cómo confirmar que funcionó y monitorar en el tiempo
Verifica la salud de los contenedores y el estado del servicio tras el deploy. Usa docker service ps para seguir la rotación de la actualización. Inspecciona el estado del healthcheck y valida el endpoint /ready pasando por el proxy.
Monitorea fallos de healthcheck y tasas de error de readiness. Integra logs y alertas. Para métricas y errores de aplicación, consulta métricas del PHP-FPM para Prometheus y un servicio de observabilidad PHP con Sentry.
- Confirma el estado de health en las tasks.
- Valida /ready vía el proxy antes de liberar tráfico.
- Recolecta logs y métricas de PHP-FPM y del proxy.
# Ver tasks y actualizaciones
docker service ps --no-trunc my_app
# Inspeccionar una task específica
ID=$(docker service ps -q my_app | head -n1)
docker inspect $ID | jq '.[0].Status.ContainerStatus.ContainerID'
# Probar readiness vía proxy (ajusta host)
curl -fsS http://app.example.com/ready || echo "not ready"
Errores comunes que rompen los healthchecks en producción
Algunos patrones causan inestabilidad y loops de reinicio innecesarios. Revisa estos puntos antes de subir a producción y tras cambios infraestructurales.
Evita checks costosos, tiempos demasiado ajustados y dependencias ocultas. Prueba bajo latencia realista. Esta guía se centra en Swarm; para Compose, usa el material enlazado anteriormente.
- HEALTHCHECK sin start_period e interval adecuados.
- Script de check que realiza I/O pesado o bloqueos de base de datos.
- Timeouts largos que retrasan la detección de fallos reales.
- Confiar en la mesh de Swarm para la readiness del tráfico.
- Esperar que depends_on actúe como gate de readiness en Swarm.
- Endpoint /ready que por error ejecuta migraciones.
Preguntas frecuentes
¿Docker Swarm usa el HEALTHCHECK para sacar réplicas del balanceo?
No. Swarm mantiene las tareas RUNNING en el pool incluso si el HEALTHCHECK falla. Para readiness de tráfico, usa health checks en el proxy (por ejemplo, verificar /ready) o un balanceador externo que retire instancias malas.
¿Debo validar base de datos y Redis en el healthcheck de PHP?
Sí, cuando son dependencias críticas. Valida con operaciones ligeras, como SELECT 1 y PING. Usa timeouts cortos y no ejecutes migraciones ni tareas costosas en el healthcheck para evitar inestabilidad.
¿Qué usar para controlar orden y calentamiento en el update de Swarm?
Usa update_config con order=start-first, delay y monitor. Esto calienta la nueva task antes de detener la antigua. Aun así, combínalo con readiness en el proxy para sólo liberar tráfico cuando /ready responda 200.
¿Puedo usar depends_on para garantizar que la base de datos esté lista en Swarm?
No. depends_on no es un gate de readiness en Swarm. Usa un entrypoint que espere las puertas del DB y cache con timeout y fallo controlado, además de healthchecks y readiness en el proxy.
¿Qué intervalos y timeout debo usar en los healthchecks?
Depende del tiempo de arranque y de la latencia esperada. En general, intervalos de 10–30s, timeout de 2–5s y un start_period suficiente para el calentamiento funcionan bien. Ajusta según pruebas bajo carga y monitoriza falsos positivos.
¿Quieres que tus health checks en Swarm sean fiables?
Si necesitas revisar el HEALTHCHECK en PHP, la readiness en el proxy y la estrategia de update del servicio, hablemos para diseñar una estrategia segura para tu stack.
Hablar sobre health checks en SwarmVer también
- Guía práctica: configurar failover activo‑pasivo entre dos VPS con Keepalived, HAProxy y lsyncd para uploads sincronizados
- Guía: checklist técnico para preparar un VPS Debian con Docker Compose para aplicaciones PHP en producción
- Guía práctica para dimensionamiento de VPS y tuning de PHP‑FPM para tiendas Magento/OpenMage con picos estacionales: del dimensionamiento a la prueba de carga
- Guía: cómo planificar y ejecutar pruebas de carga en aplicaciones PHP monolito usando k6 y Docker Compose — paso a paso