Marcio Cunha

Container travando no boot? Como ler logs do systemd no Docker

Descubra como rastrear falhas de inicialização em containers Linux usando journald e inspeção de processos em segundo plano quando o systemd trava.

Marcio Cunha•5 min
Também disponível em:EnglishEspañol
Resumo
  • O systemd atua como gerenciador de processos e serviços dentro do sistema operacional, controlando a inicialização de rotinas críticas.
  • Containers que rodam systemd internamente precisam de privilégios especiais de montagem para interagir com o kernel do host.
  • O journald coleta e armazena logs estruturados que permitem auditar falhas de boot de forma centralizada e eficiente.
  • Comandos de inspeção profunda ajudam a identificar serviços mortos ou travados antes que o container descarregue os logs.
  • Ajustar volumes e variáveis de ambiente evita que o processo principal encerre prematuramente durante a carga.

Por que containers travam na inicialização e o papel do systemd

Quando um container Docker é iniciado, o comportamento padrão é executar um único processo principal, muitas vezes chamado de PID 1 (o primeiro processo do sistema operacional). No entanto, em cenários onde precisamos rodar múltiplos serviços interdependentes dentro do mesmo container — como servidores web, bancos de dados locais e tarefas agendadas —, recorremos ao systemd, que é o software responsável por inicializar, gerenciar e monitorar todos os serviços de um sistema Linux de forma organizada.

O problema é que o systemd foi desenhado para rodar diretamente sobre o hardware ou em máquinas virtuais completas, e não dentro de um ambiente isolado de container. Quando tentamos inicializá-lo sem as permissões adequadas, ele perde o acesso a recursos vitais do kernel (o núcleo do sistema operacional que gerencia o hardware), resultando em travamentos silenciosos logo no boot. Na prática, isso significa que o container parece rodar, mas nenhum serviço interno responde e a tela fica congelada na inicialização.

Para entender a fundo como diagnosticar e resolver esse tipo de falha, precisamos analisar as entranhas da inicialização e verificar como o subsistema de logs se comporta. Caso você já gerencie ambientes complexos, vale a pena conferir também as nossas dicas sobre como resolver travamentos de pipeline por falta de espaço em disco no Docker, pois problemas de armazenamento costumam corromper o cache de boot dos serviços.

Preparando o Docker para rodar systemd com segurança

Para que o systemd funcione dentro de um container Docker, precisamos conceder a ele permissões específicas de sistema que normalmente são bloqueadas por questões de segurança. A primeira decisão de design é evitar o uso indiscriminado do modo privilegiado total, que expõe o host a vulnerabilidades severas, utilizando em vez disso flags granulares de montagem e mapeamento de diretórios.

O systemd exige acesso de leitura e escrita ao sistema de arquivos virtual do kernel, localizado na pasta /sys/fs/cgroup, além de precisar de um mecanismo para gerenciar sinais de processos. Ao iniciar o container, precisamos mapear o volume de cgroups do host e garantir que o comando de inicialização aponte diretamente para o binário do systemd, em vez de um script shell comum que encerraria o PID 1 incorretamente.

Abaixo temos um exemplo funcional de arquivo Docker Compose configurado corretamente para permitir que o systemd inicialize sem falhas de permissão de 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

Como capturar e ler logs do journald dentro do container

Quando o systemd trava durante a inicialização, o Docker geralmente não consegue exibir mensagens úteis no comando docker logs, porque a saída padrão (stdout) do container não está recebendo os fluxos gerados pelos subserviços gerenciados pelo systemd. É aqui que entra o journald, o componente do systemd responsável por coletar, indexar e armazenar logs de texto e binários de todo o sistema operacional.

Para inspecionar esses logs em tempo real ou investigar o que aconteceu logo após o boot, precisamos acessar o terminal interno do container em execução utilizando ferramentas de linha de comando. O utilitário journalctl é a chave para filtrar eventos e descobrir exatamente qual serviço falhou em iniciar e por qual motivo o processo travou.

Você pode executar o comando abaixo para listar os erros críticos ocorridos desde a última inicialização do container:

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

Esse comando filtra o registro do journald (journalctl) especificando o boot atual (-b 0) e exibindo apenas mensagens com nível de severidade de erro (-p err). Se houver falhas em daemons de rede ou permissões negadas em arquivos de configuração, elas aparecerão imediatamente na tela.

Rastreando processos em segundo plano e falhas ocultas

Muitas vezes, o travamento no boot não gera um erro explícito no journald, mas sim um loop infinito onde um processo dependente tenta iniciar antes que o sistema de arquivos esteja totalmente montado. Para mapear essa árvore de processos em segundo plano, recorremos a comandos de inspeção profunda do estado interno do container, como o systemctl adaptado para ambientes isolados.

Ao executar o comando de status geral dos serviços, podemos identificar unidades marcadas com o estado failed (falhou) ou deactivating (desativando). Esse diagnóstico visual direto evita adivinhações e aponta o gargalo exato que está impedindo a conclusão da inicialização do container.

Execute o comando abaixo no terminal para inspecionar todas as unidades ativas e com falha no systemd:

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

Caso o container esteja sofrendo com quedas intermitentes de conectividade interna durante o boot devido a regras de firewall aplicadas pelo próprio daemon, pode ser útil correlacionar o problema com análises de tráfego de rede, conforme explicamos no artigo sobre como debugar falhas de rede em containers Docker com tcpdump.

Boas práticas para evitar travamentos de boot em produção

Garantir que containers com systemd inicializem de forma determinística exige planejamento na construção das imagens e nos scripts de entrada (entrypoints). Uma armadilha comum é tentar executar comandos que exigem rede ativa antes que a interface de loopback ou o resolvedor DNS interno estejam prontos.

Para mitigar esses riscos, utilize sempre dependências explícitas nas unidades do systemd através das diretivas After= e Requires=, garantindo que um serviço só seja acionado quando seus pré-requisitos estiverem 100% operacionais. Além disso, mantenha os logs centralizados e faça testes de carga localmente usando ferramentas de monitoramento para validar o tempo de resposta do boot antes de subir as alterações para ambientes de produção.

Em resumo, debugar o boot de containers controlados pelo systemd deixa de ser um mistério quando combinamos o mapeamento correto de cgroups, a leitura precisa dos registros do journald e a inspeção rigorosa dos estados das unidades. Dominar essas técnicas garante maior resiliência para aplicações legadas ou monolíticas que dependem de gerenciadores de serviços tradicionais dentro do ecossistema Docker.