From zero to VS Code: how I tamed cPanel in Docker and built a real-time dev environment
This was a full infrastructure troubleshooting journey. The goal was clear: edit cPanel core/plugin files from VS Code on the host and get immediate reflection inside the container, without manual copy loops.
What I needed to achieve
- run cPanel/WHM in AlmaLinux 8 containers for plugin development;
- preserve cPanel core state across container recreation;
- build reliable host-to-container real-time editing;
- avoid fragile
docker cpworkflows.
1) overlay2 teardown failure
I hit this during cleanup:
Error response from daemon: container [HASH]: driver "overlay2" failed to remove root filesystem ... dnsadmin_log: operation not permitted
I treated it as immutable/append-only attribute or lock residue in the layer.
Fix path executed:
systemctl stop docker
chattr -e -i -a /var/lib/docker/overlay2/[LAYER_HASH]/diff/usr/local/cpanel/logs/dnsadmin_log
chattr -R -i /var/lib/docker/overlay2/[LAYER_HASH]/diff/usr/local/cpanel/logs/
rm -rf /var/lib/docker/containers/[CONTAINER_HASH]*
systemctl start docker
2) /etc/fstab timing conflict in Compose bootstrap
I had touch /etc/fstab in startup, but file disappeared during boot due to mount timing over /etc.
I hardened the compose command with:
- early
fstabcreation; - required package bootstrap (
wget,perl,hostname, etc.); - SSH/root setup;
- conflicting service disablement;
- pre-systemd final
fstabcheck.
That removed bootstrap instability.
3) Volume architecture decision
I explicitly avoided direct bind mount of an arbitrary host folder into /usr/local/cpanel, because it can hide install targets and break initialization.
I used a named volume:
volumes:
- cpanel_core:/usr/local/cpanel
volumes:
cpanel_core:
This kept persistence clean and aligned with Docker-managed copy-up behavior.
4) Mapping volume source and creating VS Code bridge
I discovered mount source path with:
docker inspect cpanel-server --format '{{ range .Mounts }}{{ .Source }}:{{ .Destination }}{{ "\n" }}{{ end }}'
Then exposed it to my dev workspace:
ln -s /var/lib/docker/volumes/project_cpanel_core/_data /home/user/dev
5) Final validation
Initial file test used wrong syntax. Correct absolute path test:
touch /usr/local/cpanel/teste.txt
The file appeared on host immediately, confirming real-time mirror.
Then I ran cPanel installer inside the container:
docker exec -it cpanel-server bash -c "cd /home && curl -o latest -L https://securedownloads.cpanel.net/latest && sh latest"
Post-install validation on host:
ls -la /home/user/dev/ | wc -l
71
Operational conclusion
Final setup is stable for plugin development: named volume persistence, host bridge for VS Code, and defensive bootstrap that survives real-world container lifecycle issues.
Related project: https://perciocastelo.com.br/projetos/en/docker-cpanel-dev-environment.html Repository: https://github.com/sr00t3d/docker-cpanel
This post is licensed under CC BY-NC.
Comments
Join the discussion below.
Comments are not configured yet. Add Cusdis settings in /assets/json/config/blog-comments-config.json.