Docker vs LXC on Proxmox: What I Actually Run in Production
Advertisement
Every time I bring a new Proxmox host online, someone asks: "Why not just run everything in Docker?" It's a fair question. Docker images are portable, the ecosystem is huge, and developers already know how to write a Dockerfile. But after years of managing mixed workloads—MariaDB Galera clusters, PostgreSQL, Redis, RabbitMQ, plus whatever app stacks clients hand me—I've settled into a rigid split.
LXC for stateful and long-lived services
For databases, caches, and message queues, I reach for LXC containers directly on the Proxmox host. LXC shares the host kernel, so there's zero virtualization tax. Disk I/O and memory behave exactly like they would on bare metal. For a MariaDB Galera node or a Redis instance, that lack of overhead shows up immediately in benchmarks, especially on smaller VPS-class hardware.
The other reason is purely operational. These services live for years. I want to be able to pct enter the container, check iostat, tune innodb_buffer_pool_size, or grab a pg_dump without an extra container runtime abstracting the filesystem. Backups at the Proxmox level (vzdump) just work, and restoring a single LXC is a five-minute job.
Why Docker-in-LXC never makes the list
I tried the Docker-in-LXC route early on. It looked like the best of both worlds: LXC's lightness plus Docker's packaging. In practice, stacking two layers of containerization on one kernel is fragile. It breaks at the worst possible times.
You have to enable nesting and loosen the AppArmor profile, instantly eroding the security benefits LXC provided. Then, a routine kernel update on the host quietly breaks the overlay storage driver inside the nested Docker daemon, and you only find out when containers refuse to start after a reboot.
Newer Proxmox releases added native OCI image support inside LXC. That's a genuinely useful middle ground: you can pull a standard image and run it as an LXC without a Docker daemon. I use that for small, stateless services. But if there's a database underneath it, I keep my distance.
Docker, but inside a VM
When a client hands me an app packaged as a Dockerfile or a docker-compose stack, it goes into its own Proxmox VM. Not an LXC.
The VM gives Docker a real, isolated kernel. Proxmox host kernel updates don't ripple into the container runtime, and the iptables rules Docker loves to rewrite stay contained to the VM instead of fighting the host's firewall config.
Yes, it's an extra layer of virtualization compared to Docker-in-LXC. But I've never been paged at 3 AM because a host kernel update broke a nested Docker daemon. For production workloads, that trade-off is worth it every single time.
The actual split
If I had to write it as a rule: stateful infrastructure (databases, queues, caches) runs as LXC directly on Proxmox. Application containers run as Docker inside a VM. Small stateless utilities increasingly run as native OCI-in-LXC.
None of this is dogma. If a workload genuinely needs Kubernetes, that's a different conversation. But for the small-to-mid-size infrastructure I manage, this split is boring and predictable. And boring is exactly what you want from your infrastructure.
Advertisement