Voltar para blog

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

09/03/2026 · 4 min · Docker

Compartilhar

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

Subir cPanel dentro de container não é tarefa “aperta play”. O stack mistura requisitos de sistema, comportamento de filesystem e bootstrap sensível de serviços. Meu objetivo era direto: editar core/plugin do cPanel no VS Code do host e refletir em tempo real no container, sem ciclo manual de cópia.

Nesse artigo eu registro exatamente a execução de ponta a ponta: erro real, hipótese, validação, correção e arquitetura final que ficou estável.

Objetivo operacional

Passo 1: overlay2 travando remoção de container

O primeiro bloqueio apareceu no reset do ambiente:

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

Diagnóstico aplicado

Esse padrão aponta para atributo especial no arquivo alvo (imutável +i ou append-only +a) e/ou lock residual no layer do overlay2. O Docker tenta remover a camada, o kernel nega o unlinkat, e o container vira “zumbi” no teardown.

Correção executada no host

  1. Parei o daemon para liberar locks de camada.
systemctl stop docker
  1. Limpei atributos extras no arquivo e diretório afetado.
chattr -e -i -a /var/lib/docker/overlay2/[HASH_DA_CAMADA]/diff/usr/local/cpanel/logs/dnsadmin_log
chattr -R -i /var/lib/docker/overlay2/[HASH_DA_CAMADA]/diff/usr/local/cpanel/logs/
  1. Removi artefatos residuais do container no filesystem local.
rm -rf /var/lib/docker/containers/[HASH_DO_CONTAINER]*
  1. Subi o Docker novamente.
systemctl start docker

Com isso, limpei a base para um provisionamento limpo.

Passo 2: conflito de boot com /etc/fstab

No segundo ciclo, a instalação do cPanel quebrava por ausência de /etc/fstab, mesmo com touch no command do Compose.

Causa raiz

Eu estava montando volume sobre /etc. Em timing de inicialização, o mount podia sobrepor o estado criado no início do script, fazendo o fstab “sumir” no meio do bootstrap.

Ajuste estrutural do command

Reescrevi o comando com defesa em profundidade:

command: >
  /bin/bash -c "
  # Garante o fstab logo de cara
  mkdir -p /etc && touch /etc/fstab &&

  # Dependencias essenciais para bootstrap do cPanel
  dnf install -y openssh-server passwd systemd iptables-services network-scripts wget perl hostname &&

  # SSH + root
  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 &&

  # Neutraliza servicos que conflitam no container
  systemctl stop firewalld.service || true &&
  systemctl disable firewalld.service || true &&
  systemctl stop NetworkManager || true &&
  systemctl disable NetworkManager || true &&

  # Re-garante fstab antes do systemd
  [ ! -f /etc/fstab ] && touch /etc/fstab;

  systemctl enable sshd &&
  exec /usr/lib/systemd/systemd"

Esse ajuste eliminou intermitência no bootstrap e deixou o ambiente previsível para instalação.

Passo 3: arquitetura de espelhamento (sem bind mount destrutivo)

Meu alvo era editar em /home/user/dev no host e refletir direto em /usr/local/cpanel no container.

A tentação inicial era bind mount direto:

- /home/user/dev:/usr/local/cpanel

Por que descartei esse caminho

Se a pasta do host estiver vazia ou desalinhada, você sobrepõe o destino da instalação e “esconde” o conteúdo que o instalador precisa gravar. Resultado: setup inconsistente, cópia manual e alto risco de drift.

Solução adotada

Usei volume nomeado para /usr/local/cpanel, permitindo que o Docker gerencie o armazenamento persistente e faça copy-up no primeiro ciclo:

volumes:
  - cpanel_core:/usr/local/cpanel

volumes:
  cpanel_core:

Com isso, a instalação populou o volume, e eu passei a consumir esse mesmo volume no host via symlink.

Passo 4: descobrir caminho real do volume e criar ponte para o VS Code

Para identificar a origem real no host, usei docker inspect:

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

Saída relevante:

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

Depois criei a ponte de trabalho:

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

A partir daí, abri /home/user/dev no VS Code e passei a editar direto no storage persistente do container.

Passo 5: validação final de espelhamento e correção de teste

No teste inicial, cometi erro de sintaxe:

touch teste.txt /usr/local/cpanel/

Isso não criou o arquivo onde eu queria. Corrigi usando caminho absoluto:

touch /usr/local/cpanel/teste.txt

No host, o arquivo apareceu instantaneamente em /home/user/dev, confirmando que o espelhamento estava funcional.

Depois executei a instalação do cPanel no container:

docker exec -it cpanel-server bash -c "cd /home && curl -o latest -L https://securedownloads.cpanel.net/latest && sh latest"

Ao final, validei o volume no host:

ls -la /home/user/dev/ | wc -l
71

Ambiente fechado: edição em tempo real via VS Code no host, refletindo no core do cPanel no container.

Boas práticas que ficaram no playbook

  1. Em erro de overlay2 com operation not permitted, validar atributos (chattr) e lock de camada antes de insistir em docker rm -f.
  2. Evitar mount sensível sobre /etc sem estratégia clara de bootstrap.
  3. Para cPanel em laboratório, preferir volume nomeado no core e não bind mount “cego”.
  4. Usar docker inspect para mapear origem real de volume antes de criar ponte de desenvolvimento.
  5. Testar espelhamento com caminho absoluto dentro do container para evitar falso negativo de validação.

Conclusão

Essa jornada mostrou que o ganho real não vem de “fazer funcionar uma vez”, mas de fechar uma arquitetura de desenvolvimento reproduzível e estável. Com volume nomeado + symlink no host + bootstrap defensivo, consegui um ambiente sólido para desenvolver plugin e ajustar core do cPanel com ciclo curto de feedback.

Projeto relacionado: https://perciocastelo.com.br/projetos/br/docker-cpanel-dev-environment.html Repositório: https://github.com/sr00t3d/docker-cpanel

CC BY-NC

Este post está licenciado sob CC BY-NC.

Comentários

Participe da discussão abaixo.