On platforms such as Proxmox VE, every time you create a new service the same question comes up: virtual machine or LXC container? Both look like small independent computers, with their own IP address and their own system, but they work very differently. Understanding the difference avoids wasted resources and nasty surprises.
Two different ways of isolating
A virtual machine emulates an entire computer: virtual processor, memory, disk, network card, firmware. Inside it runs a complete operating system with its own kernel. The hypervisor, helped by the processor's hardware extensions, keeps it separate from the host and from other virtual machines.
An LXC container emulates nothing. It is a set of processes running directly on the host's kernel, isolated through Linux kernel mechanisms such as namespaces (which give the container its own view of processes, network, users and filesystem) and cgroups (which limit its CPU and memory use). From the inside it looks like a complete Linux system, but the kernel is the host's.
LXC containers are also called "system containers", to distinguish them from application containers like Docker's: an LXC container hosts an entire distribution with its init system, services and package manager, whereas an application container usually runs a single process.
Practical comparison
| Aspect | Virtual machine | LXC container |
|---|---|---|
| Kernel | its own | shared with the host |
| Supported systems | Linux, Windows, BSD and others | Linux only |
| Boot | tens of seconds | a few seconds |
| Memory | reserved as a block | used as needed |
| Isolation | strong | good, but thinner |
| Hardware access | PCIe device passthrough | sharing of host devices |
| Live migration | supported | usually with a restart |
When to choose an LXC container
Containers are ideal for lightweight Linux services that do not need a particular kernel:
- a local DNS server or ad blocker;
- a reverse proxy;
- a test database;
- small web services and monitoring tools.
The main advantage is efficiency. A container that does little uses little memory, because it does not have to keep a whole operating system running with its cache and base services. On a machine with 16 GB of RAM you can run far more containers than virtual machines.
Another advantage is hardware sharing: for example, the host's integrated graphics can be made available to several containers at once for video transcoding, something that with virtual machines requires exclusive passthrough or GPU virtualisation technologies.
When to choose a virtual machine
A virtual machine is the right choice when:
- you need a non-Linux system, such as Windows or a BSD-based firewall;
- you need a specific kernel, with particular modules or a version different from the host's;
- you want to run Docker simply and in a fully supported way;
- you host services exposed to the Internet or software you trust little, where stronger isolation is worthwhile;
- you need exclusive passthrough of a device, such as a disk controller or network card.
On Docker inside LXC, a clarification: it is possible, by enabling nesting and a few options, but it is a more fragile setup that can break with updates. Many people prefer a small virtual machine dedicated to Docker, hosting all the application containers.
Privileged and unprivileged containers
Proxmox creates unprivileged containers by default: the root user inside the container maps, on the host, to an unprivileged user, thanks to user ID mapping. If a process managed to escape the container, it would find itself with very limited permissions.
Privileged containers make the inner root and the host's root the same. They are sometimes more convenient, for example for mounting network shares, but they greatly reduce isolation. The prudent rule is to use unprivileged containers unless there is a specific reason, and to solve permission problems with user mapping rather than by switching to privileged ones.
A sample split
In a typical homelab, a reasonable split could be:
- LXC: local DNS, reverse proxy, monitoring server, development database;
- VM: virtual firewall or router, a Docker machine for application services, a Windows test machine, services exposed to the outside.
In my work I prefer to start with a container and move to a virtual machine only when a concrete reason emerges: it is the simplest way to avoid filling memory with operating systems that do almost nothing.
In short
- A virtual machine emulates a complete computer with its own kernel; an LXC container shares the host's kernel.
- Containers are lighter, boot in seconds and use memory only when needed.
- For Windows, special kernels, passthrough, Docker and exposed services, a virtual machine is the better fit.
- Unprivileged containers are the safer default.
- Starting with a container and moving to a virtual machine only for concrete reasons avoids wasting RAM.