Do zero ao VS code como domei o cPanel no Docker e criei um ambiente dev em tempo real
Voltar para blog

Do zero ao VS code como domei o cPanel no Docker e criei um ambiente dev em tempo real

07/06/2026 · 10 min · Infraestrutura

Do Zero ao VS Code: Como domei o cPanel no Docker e criei um ambiente de Dev em tempo real#

Subir o cPanel dentro de contêineres Docker não é uma tarefa trivial que se resolve apenas rodando um comando básico. A pilha do cPanel mistura profundos requisitos de sistema operacional legacy, comportamento específico de sistemas de arquivos e um ciclo de bootstrap de serviços altamente sensível que interage diretamente com o gerenciador do sistema (systemd). Meu objetivo principal era direto: editar arquivos de plugins e do core do cPanel de forma nativa no VS Code instalado na minha máquina host e refletir as alterações em tempo real no contêiner, eliminando ciclos lentos de sincronização manual de arquivos.

Nesta documentação eu registro exatamente a execução dessa infraestrutura de ponta a ponta: do erro real ao diagnóstico aplicado, das correções e do código necessário para estabelecer um ambiente Dev robusto e reprodutível.


1. O cenário de desenvolvimento e cPanel em containers#

O cPanel foi projetado originalmente para rodar diretamente em servidores bare-metal ou máquinas virtuais completas onde ele assume o controle exclusivo do sistema operacional. Executar esse ecossistema dentro de um contêiner Docker que compartilha o mesmo kernel do host exige isolar adequadamente suas dependências. Nosso laboratório de desenvolvimento exige que os daemons internos do cPanel (como HTTPD, MySQL e DNSAdmin) iniciem corretamente e que o fluxo de compilação persista entre recriações do ambiente.


2. Requisitos do systemd e pré-requisitos do Docker#

O instalador e os serviços internos do cPanel dependem diretamente do systemd para gerenciar o ciclo de vida dos daemons do sistema. Executar o systemd dentro de contêineres Docker exige pré-requisitos específicos:

Nota sobre Licenciamento: O cPanel exige uma licença ativa para rodar. Para ambientes de laboratório de desenvolvimento local, deve-se utilizar uma licença do tipo Developer (disponível no portal da cPanel) ou ativar o período gratuito de testes (Trial) de 15 dias durante o primeiro bootstrap do contêiner.


3. Configuração da arquitetura (dockerfile e Docker-compose.yml)#

Para criar um ambiente estável e facilmente reprodutível, criamos uma estrutura baseada em arquivos de configuração declarativos. O arquivo de variáveis de ambiente .env na raiz deve ser usado para carregar credenciais sem expor segredos nos códigos:

# Conteúdo do arquivo .env
ROOT_PASSWORD=changeme_secure_pass_2026
SSH_PORT_CONTAINER=2222

O arquivo docker-compose.yml encapsula as permissões do kernel, montagem de cgroups e limitação de recursos do host para evitar que o contêiner esgote a CPU ou a memória da máquina de desenvolvimento:

# docker-compose.yml
version: "3.9"

services:
  cpanel-server:
    image: almalinux:8
    container_name: cpanel-server
    privileged: true
    cgroupns: host
    deploy:
      resources:
        limits:
          cpus: '4.0'
          memory: 8gb
    volumes:
      - /sys/fs/cgroup:/sys/fs/cgroup:rw
      - cpanel_core:/usr/local/cpanel
      - type: tmpfs
        target: /run
      - type: tmpfs
        target: /tmp
    environment:
      - ROOT_PASSWORD=${ROOT_PASSWORD}
      - SSH_PORT_CONTAINER=${SSH_PORT_CONTAINER}
    ports:
      - "2222:2222"   # SSH Customizado
      - "80:80"       # HTTP
      - "443:443"     # HTTPS
      - "2087:2087"   # WHM SSL
      - "2083:2083"   # cPanel SSL
    stop_grace_period: 60s
    security_opt:
      - seccomp=unconfined
    command: >
      /bin/bash -c "
      mkdir -p /etc && touch /etc/fstab &&
      dnf install -y openssh-server passwd systemd wget perl hostname &&
      echo 'root:${ROOT_PASSWORD}' | chpasswd &&
      echo 'Port ${SSH_PORT_CONTAINER}' >> /etc/ssh/sshd_config &&
      sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config &&
      sed -i 's/^PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config &&
      systemctl stop firewalld 2>/dev/null; systemctl disable firewalld 2>/dev/null; true &&
      systemctl stop NetworkManager 2>/dev/null; systemctl disable NetworkManager 2>/dev/null; true &&
      [ ! -f /etc/fstab ] && touch /etc/fstab &&
      systemctl enable sshd &&
      exec /usr/lib/systemd/systemd"

volumes:
  cpanel_core:

4. Resolução de conflitos de rede e pacotes no AlmaLinux 8#

Ao provisionar o AlmaLinux 8 dentro do Docker, algumas ferramentas de rede herdadas podem gerar erros de dependências ou interromper a compilação.

Para contornar falhas ao desabilitar o firewall de maneira segura sem mascarar erros sintáticos críticos com o operador || true, o comando de desativação deve ser expressado limpando a saída de erros padrão:

# Desabilitar firewalld de forma segura
systemctl disable firewalld 2>/dev/null; true

5. O sintoma de fstab e montagens no /etc#

Durante as primeiras inicializações do contêiner, o instalador do cPanel falhava acusando a ausência física do arquivo /etc/fstab. Isso ocorria porque montamos volumes temporários ou bindings diretamente sobre caminhos do diretório /etc/.

Essa montagem se sobrepunha ao sistema de arquivos do contêiner no momento do bootstrap, escondendo os arquivos que haviam sido criados previamente pelo comando de inicialização. Para corrigir esse conflito cronológico, o script de boot garante a existência e o toque do arquivo /etc/fstab imediatamente antes de entregar o fluxo de controle para a execução do systemd.


6. Segurança de acesso SSH via chave pública#

Expor o login de root via SSH usando senhas simples passadas por variáveis de ambiente expõe o contêiner de desenvolvimento a vetores de comprometimento.

Para enrijecer o acesso ao contêiner, adotamos autenticação exclusiva por chave SSH pública, desativando a autenticação por senha no daemon do SSH. O script de inicialização do contêiner deve configurar as chaves autorizadas no diretório do usuário root:

# Configurar diretório de chaves SSH
mkdir -p /root/.ssh && chmod 700 /root/.ssh
echo "sua_chave_ssh_publica_aqui" >> /root/.ssh/authorized_keys
chmod 600 /root/.ssh/authorized_keys

# Enrijecer o sshd_config no contêiner
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
sed -i 's/^PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config

7. Instalação segura com validação GPG#

Baixar instaladores diretamente da internet e executá-los com privilégios de administrador sem checar a integridade expõe o laboratório a ataques de cadeia de suprimentos (Supply Chain Attacks). O cPanel disponibiliza assinaturas criptográficas GPG para os seus instaladores oficiais.

Para validar a integridade e autenticidade do instalador do cPanel antes de executá-lo no contêiner, use o seguinte fluxo de comandos:

# Importar a chave pública oficial do cPanel
gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys 0x2443F8B3

# Baixar o instalador e sua respectiva assinatura GPG
curl -o latest -L https://securedownloads.cpanel.net/latest
curl -o latest.sig -L https://securedownloads.cpanel.net/latest.sig

# Validar a assinatura do arquivo
gpg --verify latest.sig latest

# Executar a instalação apenas se a assinatura for válida
sh latest

8. Arquitetura de espelhamento e volumes nomeados#

Para realizar o desenvolvimento no host em tempo real com reflexo no contêiner, precisamos espelhar o diretório de dados do cPanel /usr/local/cpanel/. Montar um diretório vazio do host diretamente sobre a pasta do contêiner via bind mount (- /home/user/dev:/usr/local/cpanel) é prejudicial, pois apaga todos os binários gravados pelo instalador durante o deploy inicial.

A solução técnica correta é usar um volume nomeado (cpanel_core). Quando o contêiner inicializa pela primeira vez, o Docker realiza a operação de copy-up, copiando os dados pré-existentes do diretório do contêiner para a área de armazenamento do volume no host, preservando a integridade dos dados originais.


9. Detecção do HASH da camada de volume#

Após o volume nomeado ser populado pelo processo de instalação do cPanel, precisamos localizar onde esses arquivos físicos residem no sistema de arquivos do host. Usando o comando docker inspect, filtramos as montagens ativas do contêiner:

docker inspect cpanel-server --format '{{ range .Mounts }}{{ .Source }}:{{ .Destination }}{{ "\n" }}{{ end }}'

A saída exibirá o caminho absoluto do volume no host:

/var/lib/docker/volumes/projeto_cpanel_core/_data:/usr/local/cpanel

Esse caminho absoluto é a origem real dos arquivos persistidos.


Com a localização exata do volume identificada no host, criamos um link simbólico apontando para a pasta de desenvolvimento do usuário local:

ln -s /var/lib/docker/volumes/projeto_cpanel_core/_data /home/user/dev/cpanel-core

Ao abrir a pasta /home/user/dev/cpanel-core no VS Code do host, o desenvolvedor pode visualizar, editar e criar arquivos de código diretamente. O sistema de arquivos do Docker atualiza o conteúdo no mesmo instante para os processos em execução no contêiner.


11. O erro do overlay2: operation not permitted#

Durante a remoção ou reconstrução de contêineres que executam serviços de log complexos (como o cPanel), o Docker Daemon pode retornar a seguinte falha crítica:

Error response from daemon: container [HASH]: driver "overlay2" failed to remove root filesystem: unlinkat /var/lib/docker/overlay2/[HASH]/diff/usr/local/cpanel/logs/dnsadmin_log: operation not permitted

Esse erro ocorre porque os serviços internos do cPanel configuram os seus arquivos de logs ativos com atributos especiais de segurança do sistema de arquivos Linux, como o atributo imutável (+i) ou o atributo de somente-adição (+a), impedindo que o daemon do Docker consiga executar a chamada unlinkat para limpar a camada do driver overlay2.


12. Mitigação correta contra containers zumbis#

Muitos administradores tentam forçar a remoção parando o daemon do Docker (systemctl stop docker) e removendo arquivos diretamente dentro do diretório de armazenamento do Docker com comandos imprecisos como chattr -R -i ou rm -rf /var/lib/docker/overlay2/*.

Procedimento seguro de recuperação#

Para remover contêineres zumbis travados por atributos imutáveis de arquivos internos, siga este roteiro de comandos seguros:

  1. Localize os arquivos com atributos especiais dentro do contêiner em execução e remova-os utilizando o find combinado com chattr (evitando o comando não confiável chattr -R):
   # Buscar e remover o atributo imutável de arquivos de log locais no contêiner
   find /usr/local/cpanel/logs/ -type f -exec chattr -i {} \; 2>/dev/null || true
  1. Remova o contêiner de forma forçada através da CLI do Docker:
   docker rm -f cpanel-server 2>/dev/null || true
  1. Execute a limpeza estruturada de recursos órfãos e camadas pendentes:
   # Remover contêineres órfãos e volumes inativos
   docker container prune -f
   docker volume prune -f
  1. Se o contêiner continuar preso em cache, reinicie o daemon de forma limpa para recarregar o banco de dados de estados do storage:
   systemctl restart docker
   docker system prune -a --volumes -f

13. Impacto do SELinux em distribuições RHEL-based#

O AlmaLinux 8 opera com o SELinux ativo em modo Enforcing por padrão. Quando o Docker tenta instanciar contêineres com controle do systemd e montagem de cgroups sob o SELinux ativo, a segurança do kernel pode bloquear o acesso, resultando em falhas silenciosas de boot.

Para mitigar conflitos de SELinux sem expor o host a riscos de segurança, ative o booleano do SELinux que permite o gerenciamento de cgroups por contêineres no host:

# Permitir que contêineres gerenciem cgroups sob SELinux
setsebool -P container_manage_cgroup true

Além disso, ao configurar volumes e montagens de pastas compartilhadas no docker-compose.yml, utilize a flag :z ou :Z para atualizar o contexto de rotulagem do SELinux nos arquivos do host correspondentes.


14. Isolamento de redes e controle de portas#

Como o contêiner do cPanel escuta em diversas portas sensíveis do sistema (como SSH, WHM e administração do painel), é fundamental isolar a rede do contêiner de acessos públicos não autorizados no host.


15. Plano de backup e restauração de volumes#

Como modificações no core do cPanel podem desestabilizar o painel de desenvolvimento, configure uma política de backups periódicos do volume nomeado cpanel_core para evitar perda de dados.

Exportar backup do volume#

Para gerar um arquivo compactado tarball contendo o estado atual do volume persistido, execute:

# Executar backup do volume nomeado cpanel_core para um arquivo local tar.gz
docker run --rm -v cpanel_core:/source -v $(pwd)/backup:/dest almalinux:8 \
  bash -c "tar czf /dest/cpanel_core_$(date +%Y%m%d_%H%M%S).tar.gz -C /source ."

Restaurar backup no volume#

Para restaurar o estado salvo do backup de volta para o volume nomeado, execute:

# Restaurar o estado do volume a partir do backup tarball
docker run --rm -v cpanel_core:/dest -v $(pwd)/backup:/source almalinux:8 \
  bash -c "tar xzf /source/cpanel_core_backup.tar.gz -C /dest"

16. Validação do espelhamento de arquivos#

Para garantir que o fluxo de espelhamento é estável e persiste após o desligamento ou recriação do contêiner, execute o roteiro de testes abaixo:

# 1. Criar um arquivo de teste usando caminho absoluto no contêiner
docker exec -it cpanel-server touch /usr/local/cpanel/teste_persistência.txt

# 2. Verificar se o arquivo aparece no diretório local do host
ls -la /home/user/dev/cpanel-core/teste_persistência.txt

# 3. Recriar o ambiente usando docker compose
docker compose down
docker compose up -d

# 4. Validar se o arquivo de teste continua existindo no contêiner pós-boot
docker exec -it cpanel-server ls -la /usr/local/cpanel/teste_persistência.txt

Esse teste confirma que o volume mantém o estado e que a ponte com o VS Code está sincronizada de forma bidirecional.


17. Playbook SRE de troubleshooting cPanel no Docker#

Durante a operação do laboratório de desenvolvimento local, utilize o seguinte guia rápido de resolução de problemas comuns:

  # Corrigir dono da pasta compartilhada no host
  chown -R root:root /var/lib/docker/volumes/projeto_cpanel_core/_data

18. Matriz de riscos de ambiente de desenvolvimento#

Evento de RiscoSeveridadeDescrição TécnicaMitigação Técnica Recomendada
Exposição de Privilégios (Privileged Mode)AltaO uso de --privileged desabilita o isolamento do contêiner, permitindo que processos maliciosos acessem o host.Restringir o uso desse ambiente exclusivamente para fins de laboratório de desenvolvimento local (offline).
Corrupção de Camadas (Overlay2)AltaA edição manual de arquivos do diretório /var/lib/docker danifica os metadados do daemon, travando o Docker.Nunca modificar os arquivos locais do Docker diretamente; utilizar docker system prune e reiniciar o serviço.
Invasão via SSH ExpeditivoMédiaSenhas root fracas configuradas em texto aberto facilitam varreduras e acessos indesejados ao contêiner.Desativar autenticação por senha e autorizar conexões exclusivamente via chaves públicas SSH.
Conflitos de Mount no /etcMédiaMontagens diretas sobre a pasta /etc apagam arquivos essenciais do sistema operacional, inviabilizando o boot.Utilizar scripts de inicialização que toquem e corrijam a integridade dos arquivos imediatamente antes do systemd.
Travamento por Falta de LimitesBaixaServiços pesados do cPanel podem consumir 100% de CPU ou RAM do host, congelando o computador do desenvolvedor.Configurar tetos de recursos (limits) de memória e CPU diretamente na declaração do serviço no Compose.

Este artigo foi útil?

Deixe uma reação rápida para apoiar o conteúdo:

CC BY-NC

Este post está licenciado sob CC BY-NC.

Comentários

Participe da discussão abaixo.

0 comentários