Volver al inicio

Despliegue Blue-Green en Docker Compose sin tiempo de inactividad

El artículo describe la implementación de despliegue blue-green en Docker Compose sin usar Kubernetes. Cubre aspectos de gestión de servicios web y workers en segundo plano, apagado elegante, compatibilidad con migraciones de base de datos y automatización mediante scripts de despliegue.

Despliegue Blue-Green sin Kubernetes: práctica en Docker Compose
Advertisement 728x90

# Despliegue Blue-Green Sin Kubernetes: Implementación en Docker Compose con Cero Tiempo de Inactividad

Implementar un despliegue blue-green es posible incluso sin orquestadores como Kubernetes: solo Docker Compose, nginx y una lógica de apagado elegante bien pensada bastan. Este enfoque es especialmente relevante para equipos que trabajan en servidores dedicados o máquinas virtuales, donde usar un clúster completo resulta impráctico por motivos económicos o arquitectónicos. El artículo cubre la implementación técnica del despliegue continuo para servicios web y workers en segundo plano, teniendo en cuenta las particularidades del procesamiento de mensajes y la gestión del estado.

Arquitectura Blue-Green en Docker Compose

En la configuración básica, cada aplicación se duplica: hay dos instancias independientes, blue y green. Ambas se lanzan como servicios separados en docker-compose.prod.yml, pero solo una recibe tráfico en cualquier momento. El enrutamiento lo maneja un proxy inverso (nginx en el ejemplo), que cambia la dirección upstream durante el despliegue. Principio clave: la nueva instancia se inicia completamente y pasa las comprobaciones de salud antes de detener la antigua.

La configuración requiere especificar explícitamente los puertos para cada instancia:

Google AdInline article slot
web-blue:
  ports:
    - "127.0.0.1:8002:8000"

web-green:
  ports:
    - "127.0.0.1:8003:8000"

Esto permite que nginx acceda a la instancia requerida vía localhost y un puerto específico. Esta configuración evita conflictos y simplifica la gestión del ciclo de vida.

Gestión de Workers en Segundo Plano

Los procesos en segundo plano (workers) que consumen mensajes de una cola (por ejemplo, RabbitMQ) requieren un enfoque especial. Detener simplemente el contenedor provocará pérdida de mensajes o reprocesamiento en caso de operaciones no idempotentes. La solución es implementar un apagado elegante a nivel de aplicación.

Esto se implementa mediante una clase singleton con una bandera is_accepting. Antes de procesar cada tarea, el worker verifica esta bandera:

Google AdInline article slot
  • Si is_accepting == True — se ejecuta la tarea.
  • Si is_accepting == False — el mensaje se devuelve a la cola con requeue=True.

Al recibir la señal SIGTERM, la bandera se establece en False, tras lo cual la aplicación espera a que terminen todas las tareas actuales (con un margen de 5–10 segundos) y luego se apaga. Esto garantiza que no se pierdan mensajes ni ocurran inconsistencias de datos.

Matizaciones importantes:

  • Para workers multi-proceso (por ejemplo, ProcessPoolExecutor), el estado de is_accepting debe ser accesible para todos los procesos hijos. De lo contrario, algunos consumidores seguirán procesando nuevas tareas.
  • Las operaciones no idempotentes requieren salvaguardas adicionales: el reprocesamiento puede corromper la integridad de los datos.
  • Usar una bandera distribuida (por ejemplo, en Redis) complica la arquitectura, pero puede justificarse en sistemas de alta carga.

Script de Despliegue: Lógica Paso a Paso

El script de despliegue automatiza el cambio entre instancias. La lógica es la misma para servicios web y workers, pero con puntos de entrada diferentes.

Google AdInline article slot

Etapas principales:

  • Determinar la instancia activa (analizando la configuración de nginx o la lista de contenedores en ejecución).
  • Iniciar la instancia inactiva (docker compose up -d).
  • Verificar la preparación de la nueva instancia mediante comprobación de salud (hasta 30 intentos con intervalos de 2 segundos).
  • Actualizar la configuración de nginx y ejecutar nginx -s reload.
  • Esperar a que terminen todas las solicitudes HTTP activas (normalmente 5 segundos).
  • Detener la instancia antigua (docker compose stop).

Ejemplo para un servicio web:

echo "server 127.0.0.1:${INACTIVE_PORT};" > "$UPSTREAM_CONF"
nginx -t && nginx -s reload
sleep 5
$COMPOSE stop web-${ACTIVE}

Esta secuencia garantiza que el tráfico nunca se dirija a un servicio no preparado, y la instancia antigua se detenga solo después del cambio completo.

Compatibilidad de Esquemas de BD y Migraciones

Uno de los principales desafíos en el despliegue blue-green es ejecutar dos versiones de la aplicación contra la misma base de datos simultáneamente. Para evitar errores, todas las migraciones deben ser compatibles hacia atrás.

Enfoque recomendado: actualización en dos etapas:

  • Primer despliegue: Eliminar el uso del campo/tabla obsoleto en el código, pero mantener la estructura en la BD. Tanto las versiones nueva como antigua funcionan correctamente.
  • Segundo despliegue (después del cambio completo de tráfico): Realizar la migración para eliminar elementos de esquema no utilizados.

Esto aumenta el número de operaciones, pero elimina el riesgo de que la instancia antigua falle por incompatibilidad de esquema.

Puntos Clave

  • El despliegue blue-green en Docker Compose es posible sin Kubernetes, pero requiere gestión manual de instancias y proxy.
  • El apagado elegante para workers es crítico: sin él, los mensajes pueden perderse o duplicarse.
  • Todas las migraciones de BD deben ser compatibles hacia atrás; la eliminación de campos requiere un enfoque en dos etapas.
  • La comprobación de salud de la nueva instancia es obligatoria antes de cambiar el tráfico.
  • La configuración de nginx debe actualizarse de forma atómica y validarse con nginx -t.

— Editorial Team

Advertisement 728x90

Leer después