Skip to content

Containers vs VMs

Proxmox runs two kinds of guests: VMs (KVM, full virtualization) and containers (LXC, operating-system virtualization). They look similar in the UI — both get IDs, both start and stop — but they're different machines under the hood, and picking the right one saves real resources.

The difference, plainly

A VM pretends to be an entire computer: virtual BIOS, virtual disk, virtual network card, and its own kernel. It can run any OS — Linux, Windows, BSD — because from the guest's point of view, the hardware is real.

A container pretends to be an operating system, not a computer. It shares the host's kernel and just gets its own isolated slice of everything else: its own files, its own processes, its own network address. No virtual hardware, no second kernel.

Consequences:

VM (KVM) Container (LXC)
Guest OS Anything Linux only (shares host kernel)
Memory overhead A full OS worth Almost none
Boot time Tens of seconds About a second
Isolation Strong (hardware boundary) Good (kernel namespaces), weaker
Density Fewer per host Many per host

The apartment-building analogy again: VMs are separate apartments with their own plumbing. Containers are roommates with lockable bedrooms sharing one kitchen — lighter, but you're all using the same stove.

When a container is enough

If the workload is a Linux service — a web app, a database, a media server, a DNS server, a build box — a container does the job with a fraction of the RAM. Home labs run most of their services in containers for exactly this reason.

Reach for a full VM when: the guest isn't Linux (Windows, BSD), you need a different kernel version than the host's, you want the strongest isolation, or you're testing OS installs themselves.

Making a container

Containers are born from templates, not ISOs. Get one:

  1. Click your node → local (pve) → CT Templates tab → Templates. Pick a Debian or Ubuntu template and download it. (These come from Proxmox's template repository — from the docs.)

  2. Click Create CT (top right). The wizard mirrors the VM one: ID, hostname, password, template, disk size, CPU, memory, network on vmbr0, DNS.

  3. Start it. It's up in about a second.

The pct basics

pct manages containers the way qm manages VMs (verified against the official pct(1) man page — every command below exists there):

pct list                 # all containers on this node
pct start 101
pct stop 101
pct destroy 101          # delete it entirely
pct enter 101            # open a shell inside the container
pct exec 101 -- df -h    # run one command inside it
pct config 101           # show its configuration

Honestly labeled: syntax verified against the official man page; not executed in this build environment.

pct enter is the container equivalent of SSHing in — a root shell inside the guest, no network needed.

Privileged vs unprivileged

New containers default to unprivileged: the container's root maps to a nobody-user on the host, so a container breakout gains almost nothing. This is what you want. Privileged containers exist for special cases (some nested-Docker setups); don't reach for them casually.

The one idea to keep

VMs virtualize hardware; containers virtualize the operating system. Same Linux workload, far less overhead in a container. Use VMs for other operating systems and maximum isolation; containers for Linux services. Next: where all these disks actually live, in Storage.