Verified against Proxmox VE 9.2.4 · Proxmox Backup Server 4.2.5 · Ceph Squid / Tentacle · Debian 13 (Trixie) · Linux kernel 7.0 (PVE 9.2 default) · 2026-08-12
○Not yet marked complete on this device.
“Can I run Docker in an LXC container?” is the most-asked Proxmox question
that has a one-word answer and a one-page explanation. The word is yes. The
page is why the official position is that you should not, why thousands of
estates do it anyway and are fine, and how to tell which of those two
situations you are in.
What nesting actually is
The documentation is terse and precise: nesting exposes procfs and sysfs to
allow nested containers.
That is the whole feature. It is not a privilege escalation, a capability
grant, or a Docker compatibility mode. It removes two masks.
By default PVE mounts parts of /proc and /sys inside a container as
read-only or replaces them with restricted views, because a container has no
business reading the host’s kernel state and a great deal of /sys is host
state. But a container runtime inside the container - Docker, Podman,
systemd-nspawn, or lxc again - needs to read and write those same
interfaces to create its own namespaces and cgroups. Without them it cannot
start anything.
Read-only / Safethe difference nesting makes, seen from inside
# pct exec 200 -- ls /sys/fs/cgroup/ | head -6
pct exec 200 -- cat /proc/self/cgroup
0::/ is the container’s view of its own cgroup root - a nested cgroup
namespace. That is what nesting buys, and it is what Docker’s daemon needs to
place its containers in cgroups of their own.
Configuration changeenable nesting on an unprivileged container— Changes the container config. Requires a restart. Enabling nesting alone does not change the container's privilege level.
set -euo pipefail
CTID=210
pct set "$CTID" --features nesting=1
pct reboot "$CTID"
pct config "$CTID" | grep -E '^(unprivileged|features):'
The other feature flags, and what each is for
Flag
Exposes
Typical reason
nesting=1
procfs and sysfs, for nested containers
Docker, Podman, nested LXC, some systemd units
keyctl=1
keyctl syscalls for kernel key management
systemd-based images that use the kernel keyring; some Docker builds
fuse=1
FUSE filesystem support
fuse-overlayfs, sshfs, rclone, s3fs inside the container
mknod=1
Device node creation
Legacy device-passthrough configs; see the device passthrough lesson
mount=
A named list of filesystem types the container may mount
A container that must mount NFS or CIFS itself
force_rw_sys=1
Read-write access to system filesystems
Rare; a compatibility escape hatch
For Docker in an unprivileged container, nesting=1 is the required one and
keyctl=1 is frequently needed too, depending on the images being run.
Running Docker in an unprivileged container
It works. Here is the shape of it, and the one check that most people skip.
Configuration changeprepare a container for Docker— Changes the container config and installs packages inside it. Restart required for the feature change to take effect.
Read-only / Safethe check people skip - which storage driver did Docker choose?— Read-only. This is the single most informative command about whether Docker-in-LXC is going to behave here.
If that reports overlay2, you are in good shape. If it reports vfs,
you have a problem that will not announce itself for weeks.
The decision, stated properly
The official Proxmox position is that Docker workloads belong in a VM. The
reasoning is sound and it is about support and layering, not about a specific
exploit. Here is the decision as it actually presents itself:
Situation
Answer
Why
Third-party or customer-supplied images
VM
You are not the author of the innermost code. The kernel is shared.
A regulated workload with an isolation requirement
VM
“Namespaces” will not satisfy an auditor asking about tenant separation.
Docker Compose stack you wrote, on your own cluster
LXC with nesting is defensible
Trusted code, and you gain density and instant start
Home lab, single tenant
LXC with nesting is fine
The threat model is a household
A CI runner building untrusted pull requests
VM, emphatically
This is the worst case: hostile code, by design, on every run
It needs to survive a live migration
VM
See below
Someone said “make it privileged and it works”
Stop
That is a different and much larger decision
Verification and undo
Read-only / Safea Docker-in-LXC container that is actually healthy— Read-only. Each of the four checks can fail independently and each has a different fix.
set -euo pipefail
CTID=210
# 1. Privilege level is what you think it is.
pct config "$CTID" | grep -E '^unprivileged:' || echo 'unprivileged: 0 (PRIVILEGED)'
# 2. Only the features you intended are set.
pct config "$CTID" | grep -E '^features:'
# 3. Docker chose a layer-sharing storage driver, not vfs.
pct exec "$CTID" -- docker info --format '{{.Driver}}'
# 4. On-disk usage and Docker's own accounting agree within reason.
pct exec "$CTID" -- du -sh /var/lib/docker
pct exec "$CTID" -- docker system df
Service impact possibleturn nesting back off— Restarts the container. Anything running inside Docker stops. Docker will not start again until nesting is restored.
set -euo pipefail
CTID=210
pct exec "$CTID" -- systemctl stop docker
pct set "$CTID" --delete features
pct reboot "$CTID"
pct config "$CTID" | grep -E '^features:' || echo 'no features set'
Note what the undo does not do: images and volumes under /var/lib/docker
remain on the rootfs, consuming space, with nothing able to read them. If you
are decommissioning Docker rather than pausing it, remove them before you
remove the flag, while the daemon can still enumerate what it owns.
Knowledge check
Knowledge check · 5 questions
Q1. What does features=nesting actually enable?
Q2. A container running Docker has filled its 32 GiB rootfs. docker system df reports about 2 GiB of images; du on /var/lib/docker reports 26 GiB. What is the most likely explanation?
Q3. Which situations argue for a VM rather than Docker inside an LXC container? Select all that apply.
Q4. Running pct set 210 --features keyctl=1 on a container that already has features: nesting=1 leaves it with keyctl=1 only.
Q5. A Docker container runs as root inside an unprivileged LXC container using the default mapping. What UID is it on the host?
Passing score: 75%. Answers are checked in this browser.