Proxmox Docker LXC vs VM: Which Should You Use in 2026?
Short answer: New to Proxmox? Run Docker in a small Linux VM. It has its own kernel, and Proxmox's container docs call nesting containers inside a QEMU VM "a recommended practice" for use cases needing maximum isolation and live migration. Docker in an unprivileged LXC is also possible with the nesting and keyctl features, but it's tied to the host's kernel.
If you read other guides on "proxmox docker lxc vs vm", check which Proxmox version they were written for. This guide is written for Proxmox VE 9.2, the current release on the official downloads page (checked 12 November 2026), and the commands below were checked against the official Proxmox VE and Docker documentation. They were not run on a test host for this guide, so read each step before you paste it.
What's actually different
A VM (KVM/QEMU) emulates a whole computer and boots its own kernel. An LXC container shares the Proxmox host's Linux kernel and is isolated with namespaces, cgroups, AppArmor and seccomp (Proxmox VE: Linux Container).
Docker is itself a container runtime. In a VM, Docker runs on the guest's own kernel, just like on a normal server. In an LXC, Docker creates containers inside a container, so it needs extra permissions from the host.
What Proxmox officially says
The current Proxmox VE container chapter says:
While running lightweight “Application Containers” directly offers significant advantages over a full VM, for use cases demanding maximum isolation and the ability to live-migrate, nesting containers inside a Proxmox QEMU VM remains a recommended practice. — Proxmox VE Administration Guide, Linux Container
That line is about Proxmox's own OCI application containers, but the reasoning carries over to Docker.
The keyctl feature in the pct manual is marked "For unprivileged containers only" and described as "required to use docker inside a container", and the same entry adds: "Essentially, you can choose between running systemd-networkd or docker." The nesting option "will expose procfs and sysfs contents of the host to the guest."
So Proxmox documents the settings Docker in LXC needs, and it's plain about the trade-offs. Its container docs also say: "In general, full virtual machines provide better isolation."
LXC vs VM for Docker at a glance
| Docker in an unprivileged LXC | Docker in a VM | |
|---|---|---|
| Kernel | Shares the Proxmox host kernel | Own guest kernel |
| Extra Proxmox settings | nesting=1 and keyctl=1 features |
None beyond a normal VM |
| Isolation | Namespaces, cgroups, AppArmor, UID mapping | Hypervisor boundary |
| Live migration | No; offline or restart migration only | Yes, when prerequisites are met |
| Host updates | Kernel/AppArmor changes can affect Docker | Guest kernel is independent |
| Docker install docs | Not covered by Docker's docs; needs Proxmox's nesting and keyctl features | Work unchanged |
| Resource overhead | Lower (no guest kernel) | Higher (full guest OS) |
| Best for | Trusted, low-stakes homelab stacks | Beginners, exposed or important services |
The Proxmox docs describe LXC as a way to get VM-like benefits "without the additional overhead". This guide doesn't give overhead figures; the Proxmox docs cited here don't include any.
Why host updates matter for Docker in LXC
Because an LXC shares the host kernel, a host upgrade can change Docker's behaviour inside it. The Proxmox VE 9.0 release notes listed "a known issue with nested containerization (e.g., Docker inside an LXC container)", tracked as bug #6538. On 21 July 2025, a Proxmox staff member wrote on the official forum: "A new pve-container package with version 6.0.3 has just been uploaded, it contains a fix to generates [sic] the relevant mqueue apparmor rule by default." The same post adds that "enabling keyctl and other features might still be required and is not considered a bug" (checked 12 November 2026). Docker in a VM runs on the guest's own kernel, so host-side kernel and AppArmor changes like this one don't reach it directly.
Steps: run Docker in a VM (recommended default)
Example IDs and sizes are placeholders. Change 200, local-lvm, vmbr0 and the ISO filename to match your host.
- Upload a Debian 13 ISO. Debian 13 "Trixie" is listed as supported in Docker's Debian install guide. Put the netinst ISO from debian.org on your ISO storage (for example
local). - Create the VM on the Proxmox host shell (qm manual):
qm create 200 --name docker-vm --ostype l26 --cores 2 --memory 4096 \ --scsihw virtio-scsi-single --scsi0 local-lvm:32 \ --net0 virtio,bridge=vmbr0 \ --cdrom local:iso/<debian-13-netinst-file>.iso \ --boot 'order=scsi0;ide2' --agent enabled=1 qm start 200local-lvm:32uses the documentedSTORAGE_ID:SIZE_IN_GiBsyntax to create a 32 GiB disk. - Install Debian from the VM's Console in the web UI. Choose a minimal install with the SSH server. Debian's installer guide says that if you leave the root password empty, root is disabled and your first user gets
sudo. If you set a root password instead, run the commands below as root and leave outsudo. - Install the QEMU guest agent inside the VM. Proxmox says the package "is usually named qemu-guest-agent" (QEMU Guest Agent):
Proxmox's docs also say to "make sure it is running". Then check it from the host:sudo apt install qemu-guest-agentqm guest cmd 200 ping. - Add Docker's apt repository, exactly as in Docker's Debian guide:
sudo apt update sudo apt install ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc sudo tee /etc/apt/sources.list.d/docker.sources <<EOF Types: deb URIs: https://download.docker.com/linux/debian Suites: $(. /etc/os-release && echo "$VERSION_CODENAME") Components: stable Architectures: $(dpkg --print-architecture) Signed-By: /etc/apt/keyrings/docker.asc EOF sudo apt update - Install Docker Engine and Compose:
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin - Test it:
sudo docker run hello-world. Docker's docs say this "downloads a test image and runs it in a container."
Steps: run Docker in an unprivileged LXC
Use this when the stack is trusted, internal, and easy to rebuild.
- Get a Debian template (pveam manual):
pveam update pveam available --section system pveam download local <debian-13-standard template name from the list> - Create the container with Docker's features turned on (pct manual). Set
--unprivileged 1explicitly:
On an existing container, runpct create 210 local:vztmpl/<template-file> \ --hostname docker-ct --unprivileged 1 --features nesting=1,keyctl=1 \ --cores 2 --memory 2048 --rootfs local-lvm:16 \ --net0 name=eth0,bridge=vmbr0,ip=dhcp pct start 210 pct enter 210pct set 210 --features nesting=1,keyctl=1, thenpct reboot 210. - Install Docker with the same commands as VM steps 5 and 6. You're root inside the container, so you can drop
sudo. - Test it:
docker run hello-world, then rundocker infoto see which storage driver Docker chose. - Confirm the config from the host with
pct config 210. The output should includeunprivileged: 1and afeatures:line containingkeyctl=1andnesting=1.
Can I pass a GPU to Docker in LXC or a VM?
Proxmox documents a different route for each. PCI(e) passthrough hands a whole PCI(e) device, such as a GPU, to a VM, and the dev[n] option passes a host device into a container. This section covers only the Proxmox side. Getting the GPU from the VM or container into your Docker containers isn't covered by the docs cited here, so check Docker's own documentation for that step. The Proxmox docs quoted here were checked on 12 November 2026. The commands were checked against those docs only and were not run on a test host.
VM: the whole device moves to the guest. Proxmox's PCI(e) passthrough docs describe passthrough as "a mechanism to give a virtual machine control over a PCI device from the host" and warn: "if you pass through a device to a virtual machine, you cannot use that device anymore on the host or in any other VM." It also affects migration: "PCI or USB devices that are passed through currently block live-migration" (live migration requirements).
The host requirements the docs list:
- Hardware that supports "IOMMU (I/O Memory Management Unit) interrupt remapping", in both the CPU and the motherboard. The docs say Intel systems with VT-d and AMD systems with AMD-Vi generally support this, but "It is not guaranteed that everything will work out of the box".
- IOMMU support turned on in the BIOS/UEFI. Separately, the docs say the Linux kernel enables IOMMU by default with AMD CPUs, and with Intel CPUs on kernels 6.8 or newer. On older kernels, Intel CPUs need
intel_iommu=onon the kernel command line. - The
vfio,vfio_iommu_type1andvfio_pcimodules listed in a file under/etc/modules-load.d/, thenupdate-initramfs -u -k alland a reboot. - The device in its own IOMMU group. Check with
pvesh get /nodes/{nodename}/hardware/pci --pci-class-blacklist "". The docs say sharing a group with the device's own functions (such as a GPU's HDMI audio) is fine.
Proxmox VE tries to make the device unavailable to the host automatically. If that doesn't work, the docs give two fixes: pass the device IDs to the vfio-pci module options, or blacklist the host driver. Once the device is free, its entry in lspci -nnk should include Kernel driver in use: vfio-pci; the docs say a missing "in use" line also means it's ready. Then add it with qm set 200 --hostpci0 <PCI address> (qm manual). For GPUs, the docs say "the best compatibility is reached when using q35 as machine type, OVMF (UEFI for VMs) instead of SeaBIOS and PCIe instead of PCI", and add that OVMF needs a GPU with a UEFI-capable ROM; otherwise, use SeaBIOS. The example VM above doesn't set any of these, so decide before you create it.
LXC: a host device passed into the container. Containers "use the kernel of the host system that they run on" (Linux Container). That suggests a device passed into a container is still handled by the host's kernel and drivers, not a guest kernel. This is an inference from the shared-kernel design, not a Proxmox statement. The pct manual documents dev[n], "Device to pass through to the container", with optional uid, gid, mode and deny-write settings. For example: pct set 210 --dev0 <host-device-path>,gid=<gid>. According to the release notes, the API and CLI have supported this since Proxmox VE 8.1, and the GUI since 8.2. The pct docs cited here don't list any IOMMU setup for dev[n].
What the Proxmox docs cited here don't cover: whether the host can still use a device after it's passed to a container, and whether several containers can share one GPU. If you need either, test it on your own hardware before you rely on it.
Checklist before you commit
- Decided which one you need: a VM for exposed, important or untrusted services, or an LXC for trusted, internal, easy-to-rebuild stacks
- If LXC: unprivileged, with
nesting=1andkeyctl=1, and restarted after any feature change - Not running Docker in a privileged container just to make an error go away
- Docker installed from Docker's official apt repository, and
hello-worldworks - Docker volumes and app data covered by a backup, and the backup restored once as a test
- Extra LXC mount points checked: the
backupflag only applies to volume mount points, and "The contents of bind mount points are not backed up when using vzdump" (pct docs) - Docker VM:
qemu-guest-agentinstalled andqm guest cmd <vmid> pinganswers - Release notes read before upgrading a Proxmox host that runs Docker in LXC
- Firewall rules inside the Docker host made with iptables/ip6tables (not nft) and added to the
DOCKER-USERchain. Docker's docs warn: "If you use ufw or firewalld to manage firewall settings, be aware that when you expose container ports using Docker, these ports bypass your firewall rules." They add: "Make sure that any firewall rulesets you use are created with iptables or ip6tables, and that you add them to the DOCKER-USER chain" (Docker docs: Firewall limitations)
Where Proxmox VE 9's OCI containers fit
Proxmox VE 9.1 added the ability to create LXC containers from OCI images (roadmap). The current docs say "running application containers in Proxmox VE is currently considered a technology preview." Compose-style multi-container apps appear on the roadmap as future work, not a shipped feature. For now, Docker Compose in a VM is still the sensible home for multi-container stacks.
FAQ
Can you run Docker in a Proxmox LXC container?
Yes. Use an unprivileged container, enable the nesting and keyctl features, and restart it. Proxmox's pct manual says keyctl is "required to use docker inside a container."
Is a VM or LXC better for Docker on Proxmox?
For most beginners, a VM. Proxmox's container docs say nesting containers inside a QEMU VM "remains a recommended practice" for use cases that need maximum isolation and live migration. LXC is lighter but shares the host kernel.
Can Proxmox LXC containers live-migrate?
No. Proxmox's docs say running containers cannot be live-migrated. A restart migration shuts the container down, moves it, and starts it on the target node. VMs can live-migrate when the prerequisites are met.
Should Docker run in a privileged LXC container?
Usually not. In an unprivileged container, root is mapped to an unprivileged user on the host, so most container escapes only reach that user. Proxmox says privileged containers should only be used in trusted environments.
Do Proxmox VE 9 OCI containers replace Docker?
Not yet. Proxmox VE 9 can create containers from OCI images, but its docs call application containers a technology preview. Compose-style multi-container support is listed on the roadmap as future work.
Sources
Sources checked 12 November 2026.
- Proxmox VE downloads (current version 9.2): https://www.proxmox.com/en/downloads
- Proxmox VE Roadmap and release notes: https://pve.proxmox.com/wiki/Roadmap
- Proxmox VE Linux Container chapter: https://pve.proxmox.com/pve-docs/chapter-pct.html
- pct(1) manual: https://pve.proxmox.com/pve-docs/pct.1.html
- pveam(1) manual: https://pve.proxmox.com/pve-docs/pveam.1.html
- qm(1) manual: https://pve.proxmox.com/pve-docs/qm.1.html
- Proxmox VE QEMU/KVM chapter (guest agent): https://pve.proxmox.com/pve-docs/chapter-qm.html
- Proxmox VE PCI(e) Passthrough (admin guide): https://pve.proxmox.com/pve-docs/chapter-qm.html#qm_pci_passthrough
- Proxmox bug #6538: https://bugzilla.proxmox.com/show_bug.cgi?id=6538
- Install Docker Engine on Debian: https://docs.docker.com/engine/install/debian/
- Debian netinst: https://www.debian.org/distrib/netinst
- Debian 13 Installation Guide, users and passwords (§6.3.2.1): https://www.debian.org/releases/trixie/amd64/ch06s03.en.html
- Proxmox forum, staff post on the pve-container 6.0.3 AppArmor fix (21 Jul 2025): https://forum.proxmox.com/threads/proxmox-ve-9-0-beta-lcx-docker-not-working.168626/post-784975
Further reading (not relied on for any claim above):
- Proxmox VE wiki, PCI(e) Passthrough: https://pve.proxmox.com/wiki/PCI(e)_Passthrough
- Proxmox VE wiki, PCI Passthrough (IOMMU groups, troubleshooting): https://pve.proxmox.com/wiki/PCI_Passthrough
Corrections
If something on this page is wrong, see Corrections.