LXC Dev Environments on Proxmox Replace Docker Desktop
Replace Docker Desktop with a Proxmox LXC dev container running Docker CE. VS Code Remote SSH connects in seconds and build times drop on NVMe-backed storage.
On this page
If you're running Docker Desktop on macOS or Windows and watching your fans spin up every time you start a container, there is a better way. Move your development environment into a Proxmox LXC container, connect VS Code or JetBrains over SSH, and your laptop becomes a thin client. Build times drop, disk I/O stops bottlenecking on virtualized file systems, and you get an environment any teammate can replicate from a single pct clone command.
Key Takeaways
- Docker Desktop replacement: An LXC container on Proxmox running Docker CE gives you full dev tooling without Docker Desktop's VM overhead or licensing requirements.
- Performance: On NVMe-backed Proxmox VE 9.1, compile times run 2–3× faster than through Docker Desktop's Linux VM translation layer on macOS.
- Remote IDE support: VS Code Remote SSH and JetBrains Gateway connect directly to LXC containers — IntelliSense, debugger, and terminal all run on the server.
- Container privilege: Docker-in-LXC needs either a privileged container or
nesting=1,keyctl=1feature flags — both approaches are covered below. - Clone for teammates:
pct clone 200 201 --fullgives a new developer an identical environment in under two minutes.
Why Docker Desktop Gets Painful at Scale
Docker Desktop on macOS and Windows does not run containers natively. It wraps a lightweight Linux VM and proxies all container activity through it. That proxy has real costs:
- File system translation: Bind-mounting your macOS
~/projectsfolder into a container goes through a translation layer. On a project with 50,000 node_modules files,npm installcan take 3× longer than the same operation on native Linux. - Memory overhead: The Docker Desktop VM itself consumes 2–4 GB of RAM before you run a single container.
- Licensing: Since April 2022, Docker Desktop requires a paid subscription for businesses with more than 250 employees or over $10M in revenue.
Moving your dev environment to Proxmox LXC sidesteps all three. Your container runs on bare Linux with direct NVMe access, and you pay nothing extra beyond your existing Proxmox setup. If you're still debating whether to move workloads off bare metal entirely, running everything on Proxmox covers the broader case for hypervisor-first homelabs.
How to Create a Dev Container on Proxmox
Start with a fresh Ubuntu 24.04 LXC. Either use the web UI or run this directly on the Proxmox host:
pct create 200 local:vztmpl/ubuntu-24.04-standard_24.04-2_amd64.tar.zst \
--hostname devbox \
--cores 4 \
--memory 4096 \
--swap 2048 \
--rootfs local-lvm:50 \
--net0 name=eth0,bridge=vmbr0,ip=dhcp \
--unprivileged 0 \
--features nesting=1,keyctl=1
Key decisions in that command:
--unprivileged 0creates a privileged container. Docker-in-LXC works in unprivileged containers on Proxmox VE 9.1 with kernel 6.8+, but you will hit cgroup v2 permission walls with certain images. Privileged is the pragmatic choice for a personal dev box.nesting=1is required for Docker to create its own network namespaces inside the LXC.keyctl=1lets tools like BuildKit use kernel keyrings for layer caching.- 50 GB rootfs is a starting point — Docker build cache grows faster than you expect.
Start the container and enter it:
pct start 200
pct exec 200 -- bash
Set Up SSH Access
Inside the container, install OpenSSH and add your public key:
apt update && apt install -y openssh-server curl
mkdir -p /root/.ssh
echo "ssh-ed25519 AAAA...your-public-key-here" >> /root/.ssh/authorized_keys
chmod 600 /root/.ssh/authorized_keys
systemctl enable --now ssh
Check the container's IP:
ip a show eth0
From your laptop, verify the connection:
ssh root@192.168.1.200
If you get a shell without a password prompt, you're done with this step.
Install Docker CE Inside the LXC Container
Avoid the docker.io package from Ubuntu's repos — it lags behind upstream by several minor versions. Use the official Docker CE repository:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu noble stable" \
> /etc/apt/sources.list.d/docker.list
apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Enable Docker and run a smoke test:
systemctl enable --now docker
docker run --rm hello-world
If hello-world completes successfully, Docker is fully functional inside your LXC. This is Docker CE 27.x running on Proxmox VE 9.1 with kernel 6.8 — cgroups v2 is active by default and Docker handles it cleanly with the nesting feature flag.
Common failure mode: if you see failed to create shim task: OCI runtime create failed, your container is running unprivileged without the right AppArmor profile. Fix it by switching to privileged mode:
pct stop 200
pct set 200 --unprivileged 0
pct start 200
Connect VS Code Remote SSH to Your Dev Container
VS Code's Remote SSH extension runs the extension host, terminal, debugger, and IntelliSense directly on the Proxmox LXC — your laptop only renders the UI. Install the Remote - SSH extension, then add this to your local ~/.ssh/config:
Host devbox
HostName 192.168.1.200
User root
IdentityFile ~/.ssh/id_ed25519
ForwardAgent yes
In VS Code: Ctrl+Shift+P → Remote-SSH: Connect to Host → select devbox. On first connect, VS Code installs its server component on the LXC (about 30 seconds) and then you're editing files directly inside the container with full language tooling.
JetBrains Gateway
JetBrains users get an identical experience through JetBrains Gateway. Add your SSH connection details, select which IDE to install remotely (IntelliJ, GoLand, PyCharm), and the full IDE backend runs on the LXC. On a container with 4 cores and 6 GB RAM, GoLand finishes indexing a 200k-line Go project in roughly 45 seconds — comparable to a local install on a modern laptop.
How to Handle Code Sync Between Your Laptop and the LXC
Three approaches, each with a different tradeoff:
| Method | Latency | Setup Complexity | Best For |
|---|---|---|---|
| Git only | None | Minimal | Clean workflows, CI parity |
| NFS mount | ~0.5ms on LAN | Moderate | Live editing from macOS/Windows |
| SSHFS | ~1–2ms on LAN | Low | Quick access, no server config |
Git is the cleanest option. Clone your repo inside the LXC, work there, push when done. You get the same environment as CI and there is no sync layer to break.
NFS makes sense when multiple people need live access to the same directory. Inside the LXC:
apt install -y nfs-kernel-server
echo "/root/projects 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)" >> /etc/exports
exportfs -ra
Mount on macOS:
mkdir -p ~/mnt/devbox
sudo mount -t nfs 192.168.1.200:/root/projects ~/mnt/devbox
SSHFS is the zero-config fallback. On macOS with macFUSE installed:
sshfs root@192.168.1.200:/root/projects ~/mnt/devbox -o follow_symlinks
Port Forwarding and Networking in Your Dev LXC
Because you're using vmbr0 with DHCP, the LXC gets a real LAN IP and any ports your containers expose are directly reachable from your network:
docker run -d -p 3000:3000 --name my-app my-app-image
Hit http://192.168.1.200:3000 from any machine on your LAN. No Docker Desktop port forwarding quirks, no extra NAT translation layer.
For remote access from outside your home network, a Cloudflare Tunnel on Proxmox gives you secure zero-trust access without opening any firewall ports — it works even on CGNAT connections where port forwarding is not an option.
If Docker Compose containers can reach each other but not the internet, Docker's default bridge network (172.17.0.0/16) likely conflicts with an existing LAN route. Adjust the address pool in /etc/docker/daemon.json:
{
"default-address-pools": [
{"base": "10.20.0.0/16", "size": 24}
]
}
Restart Docker after editing:
systemctl restart docker
How to Clone the Environment for Your Team
Once your devbox is working, giving a teammate an identical environment takes two minutes on the Proxmox host:
pct stop 200
pct clone 200 201 --full --hostname devbox-alice
pct set 201 --net0 name=eth0,bridge=vmbr0,ip=dhcp
pct start 201
Alice gets the same Docker CE version, the same system packages, the same shell config. Hand her the LXC IP and your SSH config template, and she's productive immediately. No "it works on my machine" because everyone's machine is the same machine.
For the Docker-in-LXC security model and a deeper look at when to choose privileged vs unprivileged containers on a shared cluster, running Docker inside LXC containers on Proxmox covers the privilege tradeoffs in detail.
Resource Limits and Sizing
A reasonable single-developer starting point:
pct set 200 --cores 4 --memory 6144 --swap 4096
For heavy builds — Rust, C++, large monorepos — go to 8 cores and 8 GB. LXC overhead is minimal; you're running near bare-metal performance for compute.
To prevent one devbox from starving others on a shared Proxmox host:
pct set 200 --cpulimit 4 --cpuunits 1024
--cpulimit is a hard core cap; --cpuunits sets the relative scheduling weight when the host is under load.
One gotcha that will catch you eventually: Docker build cache grows silently inside /var/lib/docker and can fill a 50 GB rootfs within days of aggressive image building. Either schedule a periodic docker system prune -af, or add a dedicated volume at container creation time:
pct set 200 --mp0 local-lvm:100,mp=/var/lib/docker
Stop and restart the container after adding the mount point. The inotify subsystem inside LXC also deserves a mention: tools like Vite, nodemon, and Air (Go live reload) fire inotify events natively — no polling, no 200–500ms delays like you sometimes see with Docker Desktop on macOS.
Conclusion
Replacing Docker Desktop with a Proxmox LXC dev environment is a one-afternoon project that pays off immediately in build speed, environment consistency, and team onboarding time. You end up with a container you can SSH into from any device, clone for any teammate, and resize without reinstalling anything. The natural next step is securing remote access: set up a Cloudflare Tunnel on Proxmox so your devbox is reachable from anywhere without exposing SSH to the public internet.