Docker vs LXC in Proxmox: When to Use Each for Your Homelab (2026)
homelab

Docker vs LXC in Proxmox: When to Use Each for Your Homelab (2026)

Ricardo Gil
August 20, 2026
10 min read
#proxmox #homelab #docker #lxc #self-hosted

The Question Every Homelabber Eventually Asks

You've got Proxmox running, maybe a Beelink EQ12 Mini PC (~$189) humming quietly on a shelf, and you want to self-host a bunch of services: Vaultwarden, Nextcloud, Uptime Kuma, Home Assistant, Immich. Then the question hits you: should I use LXC containers or spin up a Docker VM?

This is one of the most-debated topics in the r/homelab and r/selfhosted communities, and for good reason β€” both approaches work, but they have meaningfully different trade-offs depending on your use case. After running both in production on Proxmox for over two years, here's the honest breakdown.

What LXC Actually Is (and Isn't)

LXC (Linux Containers) is Proxmox's native containerization layer. It's not Docker. LXC containers share the host kernel directly β€” there's no hypervisor, no emulation, no separate kernel image. Each LXC container gets its own filesystem, network namespace, and process space, but system calls go straight to the Proxmox host kernel.

This makes LXC containers extremely lightweight. A fresh Debian 12 LXC runs at around 30–50 MB of RAM versus a full VM which typically needs 512 MB minimum just to boot. For simple services like a DNS resolver (Pi-hole), a reverse proxy (Nginx Proxy Manager), or a monitoring agent, LXC is phenomenally efficient.

The catch: LXC containers are tied to the host kernel. You can't run a Windows container, you can't use kernel modules that aren't loaded on the host, and running Docker inside an LXC container requires extra configuration (more on that below).

What Docker Is in the Proxmox Context

Docker is an application containerization runtime. In a Proxmox homelab, you typically run Docker in one of two ways:

  1. Inside a VM β€” spin up a Debian/Ubuntu VM, install Docker, run your containers there. Clean, fully isolated, works exactly like Docker on any other Linux machine.
  2. Inside an LXC container β€” run Docker within a Proxmox LXC by making it privileged (or using fuse-overlayfs for unprivileged). More efficient than a full VM, but with caveats around security and driver support.

Docker's advantage is its massive ecosystem. The Docker Hub has pre-built images for nearly every self-hosted app, and Docker Compose lets you declare multi-service stacks in a single YAML file. If you want to run Immich (which has 5 separate services), Docker Compose is the sane choice.

The Decision Matrix

Here's the framework I use when deciding which approach to take for a new service:

Use LXC when:

  • The service has a native Linux package (apt/pacman installable) β€” Pi-hole, Nginx Proxy Manager, Vaultwarden via the official binary, Home Assistant OS (as a VM, but HA Supervised in an LXC works too)
  • You need maximum density β€” LXC is the most efficient way to run many small services on limited RAM. Upgrading to 32GB DDR4 SODIMM (~$59) on a mini PC lets you run 15–20 LXC containers comfortably
  • The service doesn't have complex multi-container dependencies
  • You want Proxmox's native backup (vzdump) to snapshot the entire service cleanly

Use Docker (in a VM) when:

  • The app is distributed primarily as a Docker image (Immich, Paperless-ngx, Authentik)
  • The service requires a multi-container stack via Docker Compose
  • You need strict isolation β€” a VM has a real kernel boundary between it and the host
  • The service needs GPU passthrough (Plex transcoding, Ollama with a GPU) β€” you can pass a GPU to a VM and then let Docker use it
  • You're running untrusted or externally-exposed workloads

Use Docker inside LXC when:

  • You want Docker's ecosystem without VM overhead
  • You're comfortable with the extra configuration steps and security trade-offs
  • Your mini PC has 16 GB or less RAM and every MB counts

Setting Up a Service in LXC (Practical Example: Vaultwarden)

Let's walk through deploying Vaultwarden (a Bitwarden-compatible password manager) as an LXC container on Proxmox.

First, create the container via the Proxmox web UI or CLI. I use the Proxmox Helper Scripts project (tteck's scripts) for common services, but here's the manual approach:

bash
# On the Proxmox host
pct create 200 local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst \
  --hostname vaultwarden \
  --cores 1 \
  --memory 256 \
  --rootfs local-lvm:8 \
  --net0 name=eth0,bridge=vmbr0,ip=dhcp \
  --unprivileged 1 \
  --start 1

pct exec 200 -- bash -c "apt update && apt install -y curl"

Then inside the container, install Vaultwarden from the official binary release:

bash
pct enter 200

# Create a service user
useradd -m -s /bin/bash vaultwarden

# Download the latest binary
cd /opt
curl -L https://github.com/dani-garcia/vaultwarden/releases/latest/download/vaultwarden-$(uname -m)-unknown-linux-musl.tar.gz | tar xz
chmod +x vaultwarden

# Create data directory
mkdir -p /opt/vaultwarden-data
bash
# Create a systemd service
cat > /etc/systemd/system/vaultwarden.service << 'EOF'
[Unit]
Description=Vaultwarden Server
After=network.target

[Service]
User=vaultwarden
WorkingDirectory=/opt
Environment=DATA_FOLDER=/opt/vaultwarden-data
Environment=DOMAIN=https://vault.yourdomain.com
Environment=WEBSOCKET_ENABLED=true
ExecStart=/opt/vaultwarden
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

systemctl enable --now vaultwarden

Vaultwarden runs with 64–80 MB RAM in this configuration. In a VM, you'd need at least 256–512 MB just for the OS overhead on top of that.

Setting Up Docker in a Proxmox VM

For a multi-container stack, a dedicated Docker VM is the cleanest approach. Here's a minimal Debian 12 VM with Docker:

bash
# Inside your Debian 12 VM
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" \
  | tee /etc/apt/sources.list.d/docker.list

apt update && apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

Then deploy a stack like Immich with a single compose file:

yaml
# /opt/immich/docker-compose.yml
services:
  immich-server:
    image: ghcr.io/immich-app/immich-server:release
    volumes:
      - /mnt/photos:/usr/src/app/upload
      - /etc/localtime:/etc/localtime:ro
    env_file: .env
    ports:
      - "2283:3001"
    depends_on:
      - redis
      - database
    restart: always

  redis:
    image: docker.io/redis:6.2-alpine
    restart: always

  database:
    image: docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0
    env_file: .env
    volumes:
      - pgdata:/var/lib/postgresql/data
    restart: always

volumes:
  pgdata:
bash
cd /opt/immich && docker compose up -d

Running Docker Inside an LXC Container

If you want Docker's ecosystem without a full VM, you can run Docker inside a privileged LXC. This is a middle ground β€” more efficient than a VM, but less isolated than one.

In Proxmox, edit the LXC config file:

bash
# On the Proxmox host, edit /etc/pve/lxc/101.conf (replace 101 with your container ID)
# Add these lines:
features: keyctl=1,nesting=1
lxc.apparmor.profile: unconfined
lxc.cap.drop:

Or for an unprivileged container using fuse-overlayfs (more secure but more complex):

bash
# Inside the LXC container
apt install -y fuse-overlayfs

# Edit /etc/docker/daemon.json
cat > /etc/docker/daemon.json << 'EOF'
{
  "storage-driver": "fuse-overlayfs"
}
EOF

systemctl restart docker

The fuse-overlayfs approach lets you keep the container unprivileged while still running Docker. Performance is slightly lower than native overlay2, but for typical homelab workloads you won't notice.

Storage Considerations

One often-overlooked factor: storage throughput. Both LXC containers and Docker VMs benefit massively from fast NVMe storage. Running many containers on a spinning HDD creates I/O bottlenecks quickly. A WD Black 2TB SN850X NVMe SSD (~$129) as your Proxmox data store changes the experience entirely β€” container startups and snapshot operations that took 30 seconds on HDD finish in under 3 seconds.

For networking between containers and the host, adding a TP-Link 2.5G USB Ethernet Adapter (~$22) to your mini PC gives you enough bandwidth to move backups and large files without saturating the link used by your services.

Backups: LXC Has the Edge

Proxmox's built-in backup tool (vzdump) works natively with LXC containers. You can snapshot and restore an entire LXC β€” including all running services and their data β€” from the Proxmox web UI in seconds. Scheduling this via the Datacenter β†’ Backup UI takes two minutes to configure.

For Docker VMs, you have two choices: either backup the entire VM (which works but creates large backup files), or mount your Docker volumes on a dedicated storage path and back that up separately with something like restic or borgbackup. The LXC approach is simpler and more space-efficient for most use cases.

Performance Reality Check

In practice, the performance difference between LXC and a Docker VM for typical homelab services (web UIs, databases, media servers) is negligible. Both will feel fast on modern hardware. The meaningful differences are:

  • Boot time: LXC containers start in under 1 second. VMs take 10–30 seconds.
  • RAM overhead: LXC containers use only what the service needs. VMs need 256–512 MB minimum for the OS.
  • Density: On a 16 GB system, you can comfortably run 20+ LXC containers. Running 20 VMs would exhaust RAM quickly.
  • Isolation: VMs have a hard kernel boundary. A compromised Docker container in a VM cannot affect the Proxmox host. A compromised privileged LXC container potentially can.

My Personal Setup

For reference, here's how I've organized services across both approaches on a Proxmox node:

  • LXC containers: Pi-hole, Nginx Proxy Manager, Vaultwarden, Uptime Kuma, Netdata, Tailscale exit node, Headscale
  • Docker VM: Immich, Paperless-ngx, Authentik, Portainer (for managing the other Docker containers)
  • Docker in LXC: n8n + Ollama stack (where I needed Docker Compose but wanted to keep RAM usage low)

This hybrid approach gives me the best of both worlds: efficient, native-feeling LXC containers for simple services and Docker's ecosystem for complex multi-service apps.

The Bottom Line

Don't treat this as a binary choice. Use LXC when a service has a clean native Linux install path and you want maximum efficiency. Use Docker (in a VM) when an app is Docker-native, multi-container, or needs strict isolation. Use Docker inside LXC when you're RAM-constrained and willing to do a bit of extra configuration.

Proxmox's strength is precisely that it handles all three approaches natively β€” you're not locked into one paradigm. Start with LXC for simple services, add a Docker VM for complex stacks, and let the workload dictate the tool.

πŸ“¬Weekly Newsletter

Get the best home lab & AI content

No spam. One email per week. Unsubscribe anytime.

Share this article