Rodar o cPanel/WHM dentro de um container Docker pode parecer incomum pela arquitetura tradicional do painel, mas em cenários de teste, laboratórios locais e desenvolvimento isolado, torna-se um exercício prático muito interessante.
Recentemente, enfrentei uma jornada de testes para inicializar um container cPanel com o Systemd como PID 1. O que começou com um simples ajuste de sintaxe no YAML evoluiu para investigações sobre a transição de Cgroups v1 para Cgroup v2, falhas de alocação de escopo no Systemd e uma armadilha clássica de persistência de volumes no Docker.
Abaixo, compartilho o passo a passo, os erros analisados e a configuração final que tornou o setup funcional.
1. O primeiro tropeço: sintaxe no compose#
A ideia inicial era subir um container baseado em AlmaLinux 8, instalando pacotes base (openssh-server, passwd, iptables-services, systemd, rsyslog, wget, perl) no primeiro boot e passando o controle para o /usr/lib/systemd/systemd como PID 1.
Ao rodar o docker compose up, me deparei com o erro:
YAMLSemanticError: Implicit map keys need to be followed by map values
Causa raiz#
Ao inspecionar o arquivo, identifiquei um resquício colado do prompt do terminal no final dos volumes:
volumes:
cpanel_home:
cpanel_etc:
cpanel_var:
cpanel_usr:
cpanel_logs:
cpanel_core:root # <-- string "root" colada após os dois pontos
No YAML, chaves vazias em mapeamentos de topo exigem blocos explícitos {}:
volumes:
cpanel_home: {}
cpanel_etc: {}
cpanel_var: {}
cpanel_usr: {}
cpanel_logs: {}
cpanel_core: {}
2. O console mudo e o socket de syslog#
Com o arquivo corrigido, executei docker compose up e o container travou em:
Attaching to cpanel
Nenhum log de boot ou saída do dnf aparecia no terminal. Além disso, o cPanel depende do socket /dev/log para emissão de logs clássicos.
Soluções aplicadas:#
- Alocação de Pseudo-TTY: O Systemd verifica se está conectado a um console real (
/dev/console). Sem TTY, ele silencia o stdout. Adicionei ao Compose:
tty: true
stdin_open: true
- Instalação do rsyslog: Adicionei o pacote
rsyslogno script de bootstrap para garantir a criação e o consumo do socket/dev/logem paralelo aosystemd-journald.
3. O desafio dos Cgroups: v1 legada vs. v2 unificada#
Com o terminal exibindo a saída, surgiu a falha crítica do Systemd:
Welcome to AlmaLinux 8.10 (Cerulean Leopard)!
Failed to create /init.scope control group: No such file or directory
Failed to allocate manager object: No such file or directory
[!!!!!!] Failed to allocate manager object, freezing.
Freezing execution.
O que acontece no kernel?#
- O AlmaLinux 8 utiliza o Systemd 239, compilado para a hierarquia legada (Cgroup v1).
- O Kernel do host moderno opera em Cgroup v2 Puro (Unified Hierarchy).
- Ao inicializar, a função
manager_new()do Systemd tenta criar o escopo raiz em/sys/fs/cgroup/systemd/init.scope. No Cgroup v2, o controlador nomeadoname=systemdnão existe. O Kernel retornaENOENTe o processo congela.
A restrição do kernel#
Tentar criar pastas ou fazer bind mounts manuais em /sys/fs/cgroup/systemd dentro do container resulta em:
mount: /sys/fs/cgroup/systemd: permission denied.
Failed to mount cgroup at /sys/fs/cgroup/systemd: Operation not permitted
Por restrições de segurança do Kernel Linux (Top-down Constraint), um container não pode criar controladores Cgroup v1 sobre uma árvore v2 já montada pelo Host.
4. Migração para AlmaLinux 9 e a armadilha dos volumes#
A saída técnica foi migrar para o AlmaLinux 9, cujo Systemd v252 possui suporte nativo ao Cgroup v2 unificado.
Mudei a imagem no Compose para almalinux:9, baixei a nova imagem e rodei o serviço. Para minha surpresa, o erro persistiu exatamente igual:
✔ Image almalinux:9 Pulled
...
Welcome to AlmaLinux 8.10 (Cerulean Leopard)!
Failed to allocate manager object: No such file or directory
O fantasma no volume persistente#
Por que o container baixou o AlmaLinux 9, mas continuou executando o AlmaLinux 8?
No Compose, havia mapeamentos persistentes de diretórios de sistema:
volumes:
- cpanel_usr:/usr
- cpanel_etc:/etc
- cpanel_var:/var
O Docker faz a cópia dos arquivos da imagem para o volume nomeado (copy-up) apenas na primeira criação. Como o volume cpanel_usr já estava populado com os binários do AlmaLinux 8 das tentativas anteriores, o Docker montou o volume antigo por cima da imagem nova do AlmaLinux 9. O container estava tentando rodar o systemd 239 do Alma 8 em cima da base do 9.
A limpeza necessária#
Foi necessário remover completamente os volumes antigos:
docker compose down -v
docker volume rm public_html_cpanel_usr public_html_cpanel_etc public_html_cpanel_var
5. Estrutura final funcional no Docker compose#
Após limpar os volumes, o AlmaLinux 9 inicializou o systemd 252 sem falhas. Ajustei também o compartilhamento de namespace com cgroup: host e o sinal de parada limpa SIGRTMIN+3.
Abaixo está o arquivo docker-compose.yaml funcional:
services:
almalinux9-cpanel:
image: almalinux:9
container_name: ${CONTAINER_NAME}
hostname: ${HOSTNAME}
privileged: true
restart: always
tty: true
stdin_open: true
# Compartilha o namespace de cgroup para suporte nativo ao Cgroup v2
cgroup: host
security_opt:
- label:disable
- seccomp:unconfined
cap_add:
- NET_ADMIN
- SYS_ADMIN
- SYS_RAWIO
command:
- /bin/bash
- -c
- |
if [ ! -f /etc/firstboot_done ]; then
echo "Provisionando pacotes base no AlmaLinux 9...";
mkdir -p /etc && touch /etc/fstab;
dnf install -y openssh-server passwd systemd iptables-services wget perl hostname rsyslog;
echo "root:${ROOT_PASSWORD}" | chpasswd;
echo "Port ${SSH_PORT_CONTAINER}" >> /etc/ssh/sshd_config;
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config;
systemctl enable rsyslog sshd;
touch /etc/firstboot_done;
echo "Provisionamento concluido.";
fi;
echo "Iniciando Systemd v252 (PID 1)...";
exec /usr/lib/systemd/systemd --log-level=info --unit=multi-user.target;
stop_signal: SIGRTMIN+3
tmpfs:
- /run
- /run/lock
- /tmp
ports:
- "${SSH_PORT_HOST}:${SSH_PORT_CONTAINER}"
- "${CPANEL_SSL_PORT}:${CPANEL_SSL_PORT}"
- "${WHM_SSL_PORT}:${WHM_SSL_PORT}"
- "${CPANEL_NON_SSL_PORT}:${CPANEL_NON_SSL_PORT}"
- "${WHM_NON_SSL_PORT}:${WHM_NON_SSL_PORT}"
- "${HTTP_PORT_HOST}:${HTTP_PORT_CONTAINER}"
- "${HTTPS_PORT_HOST}:${HTTPS_PORT_CONTAINER}"
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:rw
- /lib/modules:/lib/modules:ro
- cpanel_home:/home
- cpanel_etc:/etc
- cpanel_var:/var
- cpanel_usr:/usr
- cpanel_logs:/var/log
- cpanel_core:/usr/local/cpanel
environment:
- LANG=${LANG}
- TZ=${TIMEZONE}
- ROOT_PASSWORD=${ROOT_PASSWORD}
- container=docker
volumes:
cpanel_home: {}
cpanel_etc: {}
cpanel_var: {}
cpanel_usr: {}
cpanel_logs: {}
cpanel_core: {}
Lições práticas aprendidas#
- Incompatibilidade de Cgroups: O Systemd 239 (EL8) não consegue rodar dentro de containers em hosts com Cgroup v2 puro sem modificar o boot do host. A solução mais simples e limpa é utilizar uma base com Systemd 250+ (como AlmaLinux 9).
- Cuidado ao persistir /usr e /etc: Montar volumes nomeados em diretórios de binários congela o estado do sistema de arquivos. Ao trocar a versão da imagem base, limpe os volumes antigos com
docker compose down -vpara evitar que binários antigos mascarem o novo sistema. - Systemd como PID 1 exige TTY e Signals adequados: Sem
tty: trueos logs de boot são silenciados, e semSIGRTMIN+3o encerramento do container enviaSIGKILLdestrutivo antes do Systemd desmontar os serviços com segurança.
Este artigo foi útil?
Deixe uma reação rápida para apoiar o conteúdo:
Este post está licenciado sob CC BY-NC.



Comentários
Participe da discussão abaixo.
0 comentários