Run Docker on Proxmox VE 9.x with OCI Containers

Learn how to deploy Docker workloads using Proxmox VE 9.x's new OCI container format for better process isolation and lower RAM overhead than traditional LXCs.

Proxmox Pulse Proxmox Pulse
8 min read
Glass terrarium with layered transparent boxes glowing softly inside

What happens when you can run Docker workloads on Proxmox VE 9.x with proper systemd init, faster deployment times, and real resource efficiency — all without spinning up full VMs? The answer is OCI-based containers: a new container format that bridges LXC simplicity with VM-like reliability, letting your homelab or small team scale Docker deployments much more efficiently than the traditional approach.

Key Takeaways

  • Container Format — Proxmox VE 9.x ships two distinct formats: traditional unprivileged LXCs and newer OCI-based containers with full systemd init support.
  • Docker Support — Both work for Docker, but OCI containers handle cgroup management more predictably because they use a real PID namespace hierarchy.
  • Storage Matters — overlay2 on ZFS or btrfs gives the best performance; ext4 works fine but you lose copy-on-write benefits.
  • When to Choose Each — If your workload needs isolated namespaces and clean process trees, OCI containers are the better default in VE 9.x.

What Changed with Proxmox's New Container Format?

Proxmox VE has always supported LXC containers since early versions, but they've been a bit of an afterthought compared to KVM virtual machines. Traditional LXCs use OpenVZ-style namespaces — shared kernel, minimal overhead, and very fast boot times. The tradeoff is that process management can get messy when you're running multiple Docker daemons or complex workloads inside them.

With VE 9.x came a new container format: OCI-compliant containers built on top of the same LXC runtime but with real systemd init support. This means each container boots like a tiny VM — it gets its own PID namespace, proper process trees, and cgroup management that behaves predictably. For Docker workloads specifically, this matters because Docker itself relies heavily on cgroups v2 for resource accounting and network isolation.

If you've been running containers inside full KVM virtual machines (which is what many homelab guides suggest), you're paying the price of a second hypervisor layer. The OCI container approach lets you run Docker workloads directly on Proxmox with far less overhead — typically 15-30 MB RAM idle versus 200+ MB for a minimal KVM VM running Ubuntu or Debian.

For context, if you're looking at the broader homelab picture and wondering how containers fit into your infrastructure, Build a Private Cloud at Home with Proxmox VE covers the architectural decisions beyond just container choice.

How to Deploy an OCI Container for Docker Workloads

The deployment flow in VE 9.x is straightforward through both the web UI and CLI. The key difference from traditional LXC creation is that you select "OCI" as your container type rather than the default unprivileged format. Through the command line:

pct create 102 /var/lib/vz/template/oci/debian-12-standard_12.7-1_amd64.tar.zst \
    --arch=amd64 \
    --ostype=debian \
    --features=nesting=1,keys=urt \
    --hostname docker-workstation \
    --memory 2048 \
    --cpus 2 \
    --net0=name=eth0,bridge=vmbr0,ip=dhcp \
    --storage local-lvm \
    --unprivileged=0 \
    --rootfs local-lvm:16,size=32G

The --features=nesting=1 flag is critical — it enables nested container support so Docker can create its own cgroups inside the OCI container. The keys=urt feature allows USB passthrough if you need that for storage or networking hardware. Setting unprivileged=0 gives the container root-level access to devices, which Docker's daemon needs for proper device mapper operations.

After creating the container, boot it and verify systemd is running properly:

pct start 102
ssh root@docker-workstation "systemctl status"

You should see systemd as PID 1 with a clean process tree — not the flat structure you get in traditional LXCs.

Storage Driver Choices for Docker Inside OCI Containers

The storage driver is arguably the most important decision when running Docker inside LXC containers on Proxmox, and it's something many guides skip over entirely. The options are:

  • overlay2 (default) — Works everywhere but performs best on btrfs or ZFS where copy-on-write semantics give you free deduplication of shared layers
  • fuse-overlayfs — Better for unprivileged containers where device mapper isn't available, uses FUSE to emulate overlay behavior
  • btrfs — Native COW support; ideal when your Proxmox host runs btrfs on the root filesystem

To check what's currently configured:

pct set 102 --features=nesting=1,keys=urt
docker info | grep -i "storage driver"

For a homelab running ZFS (which is Proxmox VE's default), overlay2 with overlay2 storage driver gives you the best of both worlds. Docker layers are deduplicated at the host level while still providing fast snapshot and copy performance. If your LXC template doesn't already have Docker installed, set it up:

apt update && apt install -y ca-certificates curl gnupg
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" > /etc/apt/sources.list.d/docker.list
apt update && apt install -y docker-ce docker-ce-cli containerd.io

Networking: Bridging Docker Containers to the Outside World

Networking inside OCI containers works differently than in traditional LXCs because of how cgroups handle network namespaces. By default, Docker creates its own bridge (docker0), but this can conflict with Proxmox's vmbr0 if you're not careful about IP address management.

The cleanest approach is to let the OCI container use a dedicated VLAN or subnet and configure Docker to use it:

# On your host, verify vmbr0 exists
ip addr show vmbr0

# Inside the OCI container, set Docker's bridge network
docker network create --driver=bridge --subnet=172.20.0.0/16 docker-internal

# Verify connectivity
docker run --rm --network=docker-internal alpine ping -c 3 google.com

If you're running a homelab with VLANs (which most do at this point), Configure Parallel Sync Jobs for S3 Offsite Backups covers the networking setup that pairs well here — once your containers are on the right subnet, backup jobs become much easier to manage.

OCI Containers vs Traditional LXCs: What Actually Changes?

Not every Docker workload needs an OCI container. The question is when the extra complexity buys you something real. Here's a practical comparison:

Factor Traditional LXC (unprivileged) OCI Container KVM VM
Init system OpenVZ init or custom script systemd (PID 1) Full guest kernel boot
Process isolation Shared PID namespace Dedicated PID namespace Full separation
Docker compatibility Requires nesting=1, device mapping Native cgroup support Perfect (full kernel)
Boot time ~2-5 seconds ~3-6 seconds 10-30 seconds
RAM overhead 10-25 MB idle 15-30 MB idle 200+ MB minimum
CPU overhead Minimal (shared kernel) Low (minimal extra context switches) Moderate (hypervisor layer)

The honest tradeoff is that OCI containers give you better process management but require slightly more careful configuration. Traditional LXCs are simpler to set up and work fine for most Docker use cases, especially single-container deployments. KVM VMs remain the safest choice when you need complete isolation — for example, if you're running databases or services with different kernel requirements on the same host.

How to Back Up Your OCI Container Deployments

Once your Docker workloads are running inside OCI containers, don't neglect backups. Automated Backups with Proxmox Backup Server walks through setting up PBS for snapshot-based backups that capture both container state and filesystem changes efficiently. For a typical homelab setup, I'd recommend:

# Create a backup job for your OCI containers via the CLI
pvesr add --server 192.168.1.50 --port 8007 --username root@pam --password-file /etc/pbs-backup.key --storage pbs-storage

# Schedule daily backups at off-peak hours (adjust to your timezone)
crontab -e
# Add: 0 3 * * * /usr/sbin/vzdump 102 --mode snapshot --compress zstd --mailto admin@homelab.local

The beauty of PBS with OCI containers is that you get incremental backups at the block level — if your Docker container only changed 5 GB since the last backup, Proxmox backs up just those blocks rather than the full disk.

Managing Your Deployments: Beyond the CLI

If you prefer a visual interface alongside or instead of the web UI, Cockpit on Proxmox: Manage KVM, LXC, and Docker in One UI is worth considering for teams that want to run Docker management tools without leaving their browser. Cockpit integrates directly with Proxmox's container API while offering a more familiar dashboard experience.

For the CLI-focused crowd, keep an eye on pct commands — they're getting increasingly powerful in VE 9.x:

# List all OCI containers with details
pct list --output-format=json | jq '.[] | select(.type == "lxc") | {id, name, status}'

# Monitor resource usage of a specific container
pct monitor 102 --interval=5

Conclusion

OCI-based containers in Proxmox VE 9.x represent a genuine improvement for Docker workloads — they're not just another format choice but a meaningful step toward better process isolation without the overhead of full VMs. For most homelab and small-team deployments, an OCI container with systemd init gives you the best balance of simplicity, performance, and reliability. The next step is to migrate your heaviest Docker workloads from either traditional LXCs or KVM VMs into this format and measure the difference yourself — in my experience, the process management improvements alone justify the configuration effort.

Share
Proxmox Pulse

Written by

Proxmox Pulse

Sysadmin-driven guides for getting the most out of Proxmox VE in production and homelab environments.

Related Articles

View all →