Proxmox OCI LXC: Docker Swarm and K3s Backup Setup

Run Docker Swarm or K3s inside a Proxmox OCI LXC guest on one bridge network, keeping all state inside the guest for reliable backup and restore in one place.

Proxmox PulseProxmox Pulse
9 min read
A glass cube on a dark table beside server hardware under cool cinematic lighting.

On Proxmox VE 9.1, OCI LXC containers give you a clean way to run OCI images as first-class Proxmox guests, but Docker Swarm and K3s each bring their own network and storage assumptions. This guide shows how to put one OCI LXC base on a Proxmox bridge, run either Swarm or K3s inside it, and keep backup in one place instead of stitching two systems together.

Key Takeaways

  • One guest: Put the orchestrator inside an OCI LXC so Proxmox can back it up as a single unit.
  • One network: Keep LXC networking on Proxmox bridges or SDN zones, and let only the overlay or pod CIDR belong to the runtime.
  • One storage owner: Store runtime data inside the LXC rootfs unless you have a backup plan for mounted volumes.
  • One upgrade path: Docker Swarm is simpler to run, but K3s gives Kubernetes APIs at the cost of more moving parts.

How to keep one network and one backup path

The fastest way to make this messy is to run Docker Swarm on the Proxmox host, then also run OCI LXC guests, then wonder why backup jobs only cover half the state. The cleaner pattern is to make each orchestrator a normal Proxmox guest, then let Proxmox Backup Server handle that guest like any other LXC container.

For networking, I keep the LXC management and service traffic on an existing Proxmox bridge or SDN zone. Docker Swarm or K3s still creates its own internal overlay or pod network, but that network stays inside the guest. The host network only carries IP traffic between guests, not the full Kubernetes or Swarm data plane.

If your bridge is VLAN-backed, keep the guest network on the same VLAN you already use for services. If you are choosing between VLAN and VXLAN for the underlying fabric, see VLAN vs VXLAN in Proxmox VE. The rule is simple: pick one network owner for the host side, and give the runtime its own non-overlapping CIDR inside the guest.

net0: name=eth0,bridge=vmbr0,tag=30,ip=10.20.30.10/24,gw=10.20.30.1
features: nesting=1,keyctl=1
unprivileged: 1

For backup, the rule is equally simple: if the data lives inside the LXC rootfs, Proxmox Backup Server can back it up. If you mount extra Proxmox storage into the guest, decide whether that mount belongs in the backup before you add it. Do not let Docker or K3s quietly write to a host path that Proxmox Backup Server never sees.

How to set up an OCI LXC base for both stacks

For the OCI image import path, I followed the setup in OCI Image Containers in Proxmox VE 9.1. The Debian OCI image pulled in about 120 MB on my test node, which is small enough that I do not worry about image size until the guest starts storing runtime data.

I use an LVM-thin storage pool for the orchestrator guest because Docker and K3s are less fussy about the underlying filesystem than ZFS can be. If you use ZFS, test the storage driver behavior before you put anything production-like on it.

pct create 101 oci:debian:12 --rootfs local-lvm:20 --unprivileged 1 --features nesting=1,keyctl=1 --net0 name=eth0,bridge=vmbr0,tag=30,ip=10.20.30.10/24,gw=10.20.30.1 --onboot 1

After the guest exists, I set memory and CPU, then start it. The create command already includes the nesting and keyctl features because both Docker and K3s need them when running inside an unprivileged LXC container.

pct set 101 --memory 2048 --balloon 0 --cores 2
pct start 101

For the K3s guest, I repeat the same pattern with a second OCI LXC container and more memory. K3s is lighter than full Kubernetes, but it is not a single-container toy once you add workloads, ingress, and local storage.

pct create 102 oci:debian:12 --rootfs local-lvm:20 --unprivileged 1 --features nesting=1,keyctl=1 --net0 name=eth0,bridge=vmbr0,tag=30,ip=10.20.30.11/24,gw=10.20.30.1 --onboot 1
pct set 102 --memory 4096 --balloon 0 --cores 4
pct start 102

I start with unprivileged guests and the nesting and keyctl features. If Docker needs more kernel capabilities, switch that one orchestrator guest to privileged and keep the plain OCI LXC workloads unprivileged. For the privileged versus unprivileged tradeoff, see Docker LXCs on Proxmox.

Docker Swarm on OCI LXC: simple service orchestration

Docker Swarm is the lighter option here. If your services are already Docker images and you only need replicas, secrets, rolling updates, and a simple overlay network, Swarm keeps the setup small. The OCI LXC guest becomes the Swarm manager, and Proxmox still owns the guest lifecycle and backup.

I tested this with Docker Engine 27.5.1 inside the Debian OCI LXC guest. The install steps are the normal Debian repository path, then Swarm init runs inside the container.

pct enter 101
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 -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] 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

Initialize the Swarm manager inside the guest, then create the overlay network that services will use. The overlay network stays inside the guest network namespace, so Proxmox only sees the container IP and the bridge network.

docker swarm init --advertise-addr 10.20.30.10 --data-path-addr 10.20.30.10 --listen-addr 0.0.0.0:2377
docker network create --driver overlay --attachable --subnet 10.100.0.0/24 --opt com.docker.network.driver.mtu=1450 app-net
docker service create --name web --network app-net --replicas 3 nginx:1.27

The first gotcha I hit was MTU. When Docker Swarm runs inside an LXC guest on a network that already uses VXLAN or another encapsulated path, the default overlay MTU can cause packet loss. I set the Docker overlay network MTU to 1450 and the symptoms went away. If you use a larger fabric MTU, test before lowering it globally.

The honest tradeoff with Swarm is that it is simple until you need Kubernetes APIs. If you need custom resources, admission webhooks, or a large Helm catalog, Swarm is not the right place to force that model.

K3s on OCI LXC: Kubernetes without a second control plane

K3s is the better fit when you want Kubernetes-style deployment, service, ingress, and secret objects without running a full control plane on the Proxmox host. The OCI LXC guest becomes the K3s server, and the Kubernetes client talks to the API inside that guest.

I tested this with K3s v1.31.10+k3s1 inside the second OCI LXC guest. The install command pins the version so upgrades are explicit rather than surprising.

pct enter 102
apt update
apt install -y ca-certificates curl
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.31.10+k3s1 INSTALL_K3S_EXEC="--cluster-cidr 10.42.0.0/16 --service-cidr 10.43.0.0/16" sh -

After the installer finishes, the Kubernetes client can read the kubeconfig inside the guest. The cluster CIDR and service CIDR are set explicitly so they do not collide with the Proxmox bridge network.

export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
kubectl get nodes
kubectl create deployment web --image=nginx:1.27 --replicas=3
kubectl expose deployment web --port=80 --target-port=80

K3s uses its own CNI and pod network. That is fine, but do not let the pod CIDR or service CIDR overlap with the bridge network or the Docker Swarm overlay. If you are already running VXLAN in Proxmox, nested VXLAN can work, but it makes MTU and troubleshooting less pleasant. This is where the VLAN vs VXLAN in Proxmox VE guidance matters.

The honest tradeoff is that K3s gives you Kubernetes APIs, but it also gives you more moving parts than Docker Swarm. More moving parts means more upgrade testing, more version compatibility checks, and more places where backup needs to be verified.

How to compare Swarm, K3s, and plain OCI LXC

Setup Best when Backup unit Networking owner
OCI LXC only You only need a few OCI images running as normal Proxmox guests Proxmox Backup Server guest Proxmox bridge or SDN zone
Docker Swarm on OCI LXC You want Docker-native services with fewer moving parts Proxmox Backup Server guest Docker overlay inside the guest, bridge outside
K3s on OCI LXC You need Kubernetes objects, Helm charts, or Kubernetes ingress Proxmox Backup Server guest CNI inside the guest, bridge outside
Orchestrator on the Proxmox host You want the host to own the runtime state Host directories are not backed up by default Host bridge plus runtime network

For most homelab and small production setups, I would start with plain OCI LXC for simple services, Docker Swarm for Docker-only service stacks, and K3s only when Kubernetes features are actually needed. The setup is less confusing when the orchestrator is a guest that Proxmox can back up, snapshot, stop, start, and migrate like any other workload.

Backup and restore without duplicating state

The backup model is straightforward if you keep runtime state inside the guest. Docker data and K3s data live inside the LXC rootfs, so Proxmox Backup Server backs them up with the container. That avoids the common mistake where the container is backed up, but the runtime data is mounted from somewhere else and never captured.

On my test node, a 20 GB guest with Docker data completed a Proxmox Backup Server snapshot backup in about 4 minutes after the first full run. Incrementals were much smaller, which is what you want when the guest is mostly static OCI images plus a small database or config directory.

vzdump 101 --storage pbs01 --mode snapshot
vzdump 102 --storage pbs01 --mode snapshot

If you run Proxmox Backup Server, keep the sync schedule simple. The guest is the backup boundary. Do not add separate backup jobs for Docker volumes or Kubernetes local paths unless those paths are outside the guest and you have a clear retention plan. For the backup server side, Proxmox Backup Server 4.2 parallel sync jobs can shrink the window when you have multiple guests.

The tradeoff is that a single LXC backup is easy, but it is also coarse. If you need to restore one application without restoring the whole orchestrator guest, you need application-level backup inside the guest. If you need to restore the whole guest, Proxmox Backup Server is the right tool.

Conclusion

This setup keeps OCI LXC workloads, Docker Swarm, and K3s on one Proxmox network path and one backup path instead of creating a second backup boundary for each runtime. Use Docker Swarm when you want the simplest service model, and use K3s when you need Kubernetes APIs and are willing to test upgrades more carefully. Your next step is to create one OCI LXC guest, run a single test service through the chosen runtime, and verify that the backup job captures the runtime data inside the guest.

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 →