Marcio Cunha

¿Contenedor bloqueado en el arranque? Cómo leer logs de systemd en Docker

Aprende a rastrear fallas de inicio en contenedores Linux usando journald y la inspección profunda de procesos en segundo plano cuando systemd se congela.

Marcio Cunha•5 min
También disponible en:EnglishPortuguês
Resumen
  • El sistema systemd actúa como administrador de servicios dentro del sistema operativo, orquestando rutinas críticas de inicio.
  • Los contenedores que ejecutan systemd internamente requieren privilegios especiales de montaje para interactuar con el núcleo del host.
  • El demonio journald captura registros estructurados que permiten auditar de forma centralizada las fallas de arranque del contenedor.
  • Los comandos de inspección profunda ayudan a identificar servicios muertos antes de que el contenedor descargue sus registros de ejecución.
  • Un correcto mapeo de volúmenes y variables de entorno evita que el proceso principal finalice prematuramente durante la carga.

Por qué los contenedores se congelan en el arranque y el rol de systemd

Cuando se inicia un contenedor de Docker, el comportamiento predeterminado es ejecutar un único proceso principal, a menudo denominado PID 1 (el primer proceso del sistema operativo). Sin embargo, en escenarios donde necesitamos ejecutar múltiples servicios interdependientes dentro del mismo contenedor —como servidores web, bases de datos locales y tareas programadas— recurrimos a systemd, que es el software responsable de inicializar, administrar y monitorear todos los servicios de un sistema Linux de forma organizada.

El problema es que systemd fue diseñado para ejecutarse directamente sobre hardware físico o en máquinas virtuales completas, y no dentro de un entorno aislado de contenedor. Cuando intentamos iniciarlo sin los permisos adecuados, pierde el acceso a recursos vitales del kernel (el núcleo del sistema operativo que administra el hardware), lo que provoca bloqueos silenciosos justo en el arranque. En la práctica, esto significa que el contenedor parece ejecutarse, pero ningún servicio interno responde y la pantalla se congela durante la inicialización.

Para comprender a fondo cómo diagnosticar y resolver este tipo de fallas, necesitamos analizar las entrañas de la secuencia de inicio y ver cómo se comporta el subsistema de registros. Si ya administras entornos complejos, también vale la pena consultar nuestros consejos sobre cómo resolver fallas de pipeline causadas por falta de espacio en disco en Docker, ya que los problemas de almacenamiento suelen corromper la caché de arranque de los servicios.

Preparando Docker para ejecutar systemd de forma segura

Para que systemd funcione dentro de un contenedor Docker, debemos otorgarle permisos específicos del sistema que normalmente se bloquean por razones de seguridad. La principal decisión de diseño es evitar el uso indiscriminado del modo privilegiado total, que expone al host a vulnerabilidades graves, utilizando en su lugar indicadores granulares de montaje y mapeo de directorios.

Systemd requiere acceso de lectura y escritura al sistema de archivos virtual del kernel ubicado en /sys/fs/cgroup, además de un mecanismo para administrar señales de procesos. Al iniciar el contenedor, debemos mapear el volumen de cgroups del host y asegurarnos de que el comando de inicio apunte directamente al binario de systemd en lugar de a un script de shell común que terminaría el PID 1 incorrectamente.

A continuación se muestra un ejemplo funcional de un archivo Docker Compose configurado correctamente para permitir que systemd se inicialice sin errores de permisos del kernel:

version: '3.8'&#nservices:&#n  systemd-app:&#n    build: .&#n    container_name: systemd_boot_debug&#n    privileged: true&#n    volumes:&#n      - /sys/fs/cgroup:/sys/fs/cgroup:rw&#n    command: [/usr/sbin/init]&#n

Cómo capturar y leer logs de journald dentro del contenedor

Cuando systemd se congela durante el inicio, Docker generalmente no puede mostrar mensajes útiles en el comando docker logs porque la salida estándar (stdout) del contenedor no está recibiendo los flujos generados por los subservicios administrados por systemd. Aquí es donde entra journald, el componente de systemd responsable de recopilar, indexar y almacenar registros de texto y binarios de todo el sistema operativo.

Para inspeccionar estos registros en tiempo real o investigar qué sucedió justo después del arranque, necesitamos acceder al terminal interno del contenedor en ejecución utilizando herramientas de línea de comandos. La utilidad journalctl es la clave para filtrar eventos y descubrir exactamente qué servicio no se pudo iniciar y por qué motivo se detuvo el proceso.

Puedes ejecutar el comando a continuación para enumerar los errores críticos ocurridos desde el último inicio del contenedor:

docker exec -it systemd_boot_debug journalctl -b 0 -p err&#n

Este comando filtra el registro de journald (journalctl) especificando el arranque actual (-b 0) y mostrando solo los mensajes con un nivel de gravedad de error (-p err). Si hay fallas en los demonios de red o denegaciones de permisos en los archivos de configuración, aparecerán inmediatamente en la pantalla.

Rastreo de procesos en segundo plano y fallas ocultas

A menudo, un bloqueo en el arranque no genera un error explícito en journald, sino un bucle infinito donde un proceso dependiente intenta iniciarse antes de que el sistema de archivos esté completamente montado. Para mapear este árbol de procesos en segundo plano, recurrimos a comandos de inspección profunda del estado interno del contenedor, como systemctl adaptado para entornos aislados.

Al ejecutar el comando general de estado del servicio, podemos identificar unidades marcadas con el estado failed (falló) o deactivating (desactivando). Este diagnóstico visual directo evita conjeturas y señala el cuello de botella exacto que impide que el contenedor finalice su inicialización.

Ejecute el siguiente comando en su terminal para inspeccionar todas las unidades activas y fallidas en systemd:

docker exec -it systemd_boot_debug systemctl list-units --state=failed&#n

Si el contenedor sufre caídas intermitentes de conectividad interna durante el arranque debido a reglas de firewall aplicadas por el propio demonio, puede ser útil correlacionar el problema con el análisis de tráfico de red, como se explica en nuestro artículo sobre cómo depurar fallas de red en contenedores Docker con tcpdump.

Buenas prácticas para evitar bloqueos de arranque en producción

Garantizar que los contenedores que ejecutan systemd se inicien de manera determinista requiere una planificación cuidadosa en la construcción de imágenes y scripts de entrada (entrypoints). Una trampa común es intentar ejecutar comandos que requieren red activa antes de que la interfaz de bucle invertido o el solucionador de DNS interno estén listos.

Para mitigar estos riesgos, utilice siempre dependencias explícitas en las unidades de systemd a través de las directivas After= y Requires=, asegurando que un servicio solo se active cuando sus requisitos previos estén 100% operativos. Además, mantenga los registros centralizados y realice pruebas de carga locales utilizando herramientas de monitoreo para validar los tiempos de respuesta de arranque antes de promover cambios a los entornos de producción.

En resumen, depurar la secuencia de arranque de contenedores controlados por systemd deja de ser un misterio cuando combinamos el mapeo adecuado de cgroups, la lectura precisa de los registros de journald y la inspección rigurosa de los estados de las unidades. Dominar estas técnicas garantiza una mayor resiliencia para aplicaciones heredadas o monolíticas que dependen de administradores de servicios tradicionales dentro del ecosistema Docker.