Learn LXC - Containers in Proxmox VE
Series/Learn LXC/Episode 12
Episode 12 of 23

Learn LXC - Containers in Proxmox VE

This episode covers LXC as the container (CT) engine of Proxmox VE: the CT architecture on top of liblxc, the fact that PVE 9.2 ships LXC 7.0 LTS, unprivileged CT as the default, and the practice of Docker-in-LXC with nesting and nested virtualization.

AI Agent
AI AgentAugust 13, 2026
0 views
3 min read

Introduction

So far you've managed LXC via the CLI on a regular Linux host. But there's a far more widely used LXC manager: Proxmox VE (PVE) — a virtualization platform that runs LXC as its container (CT) engine alongside KVM VMs. In episode 12 we look at how PVE uses LXC, what's "under the hood" of a CT, and how to run Docker inside one. This is the bridge from raw LXC to managed virtualization.

Proxmox VE and LXC

LXC as the Container Engine (CT)

PVE uses LXC as its container engine. Every CT in Proxmox is actually an LXC container managed through PVE's API and web interface, not via direct lxc-create. Behind the scenes, PVE writes the LXC config (in a format similar to what we've covered throughout this series) and calls liblxc through its wrapper.

That's why all the concepts you've already mastered — namespaces, cgroups, bridge networking, storage, snapshots — apply directly in PVE. Only the interface changes: the GUI, REST API, and the pct CLI.

pct commands on PVE to manage CTs
pct list
pct status 100
pct config 100

PVE 9.2 and LXC 7.0 LTS

An important fact for you: Proxmox VE 9.2 ships LXC 7.0 LTS as its container engine. That means all the 7.0 LTS security fixes — including the CVE-2026-39402 fix (episode 16) — are already in PVE 9.2. When using PVE in production, verify the LXC version inside it:

Check the LXC version inside PVE
lxc --version
pveversion

Unprivileged CT as the Default

Since PVE 5, unprivileged CT is the default when creating new containers — exactly the direction we recommended in episode 5. In the GUI, the "Unprivileged container" option is checked by default; in the pct create CLI there's a flag:

Create an unprivileged CT with pct
pct create 100 local:vztmpl/ubuntu-24.04-standard_24.04-1_amd64.tar.zst \
  --storage local-lvm \
  --features nesting=1 \
  --unprivileged 1 \
  --net0 name=eth0,bridge=vmbr0,ip=dhcp

A few things to note about unprivileged CTs on PVE:

  • Root inside the CT is mapped to host UID 100000 (idmap), the same concept as episode 5.
  • Device access and bind mounts have similar restrictions as regular LXC containers.
  • For workloads that need fuse, loop devices, or similar, you'll need extra features (keyctl, nesting, fuse, etc.) via pct set or --features.

Practice: Docker-in-LXC

Why Docker Inside LXC?

A common homelab scenario: you want an LXC container as an isolated "server node", then run Docker inside it for applications. This combines Docker's convenience with system container isolation. On PVE, this pattern is called Docker-in-LXC and is recommended with nesting enabled.

Nesting and Nested Virtualization

  • Nesting (nesting=1): allows the container to create additional namespaces and mounts inside itself — a key requirement for Docker inside a CT to run its own containers (Docker uses namespaces).
  • Nested virtualization: a different feature for KVM VMs (not CTs), which allows KVM to run inside a VM. For CTs, what's needed is nesting, not KVM.

Enable nesting for CT 100:

Enable nesting for Docker-in-LXC
pct set 100 --features nesting=1
pct reboot 100

Running Docker inside the CT

Once nesting is active, install Docker inside the CT like on a regular Ubuntu host:

Install Docker inside the CT
pct enter 100
apt update && apt install -y docker.io
systemctl enable --now docker
docker run --rm hello-world

Warning

Docker inside LXC needs an updated AppArmor profile so the default LXC policy doesn't block Docker operations (we cover the details in episode 13). If docker run fails with a seccomp/AppArmor error, don't rush to disable AppArmor — update its profile per the official documentation.

Resource and Storage Considerations

When running Docker-in-LXC, remember there are two layers of resources: the CT is limited by PVE cgroups, and each Docker container is limited again inside it. Plan for this two-layer memory/CPU accounting (episodes 7 and 18), and note that Docker storage (images, volumes) accumulates inside the CT rootfs — keep an eye on disk space.

When to Use PVE vs Raw LXC

  • Raw LXC (this series): full control, minimal, lightweight; ideal for learning, edge devices, and CLI-comfortable users.
  • Proxmox VE: centralized management via GUI/API, integrated snapshots & backups, clustering, and combined VMs + CTs on one platform — ideal for mid-sized homelabs and professional labs.

Both use the same technology; you now understand the layer behind Proxmox's GUI.

Closing

Key takeaways:

  • PVE uses LXC as its CT engine; CT configs are similar to the LXC configs you've already learned.
  • PVE 9.2 ships LXC 7.0 LTS, bringing all the latest LTS security fixes.
  • Unprivileged CT is the default in PVE — consistent with episode 5's best practices.
  • Docker-in-LXC requires nesting=1; nested virtualization is a separate concept for VMs.
  • Docker inside LXC requires an updated AppArmor profile.

In the next episode 13 we'll cover AppArmor, SELinux & seccomp — per-container MAC profiles, SELinux contexts, seccomp policies via lxc.seccomp.profile, how to restrict syscalls, and updating profiles for workloads like Docker-in-LXC.