Running Docker: From a Proxmox LXC to Docker Desktop on Windows
Where I actually run Docker across my cluster, when I'd use a VM instead, and how to get Docker Desktop working on a Windows machine.
Three out of four Debian containers on my Proxmox cluster are running Docker underneath whatever they're actually there to do. It's the layer that lets me deploy most self-hosted services the same way their maintainers test them, with a docker-compose.yml instead of hand-rolling a native install for every distro quirk. This is the setup I've settled into after getting it wrong a few different ways: where I run it, where I don't, and the handful of things I wish someone had told me before my first LXC container refused to start a single container.
Where I Actually Run It: Debian LXC Containers
Most of what I self-host doesn't need a full virtual machine underneath it. A privileged Debian LXC container with nesting turned on boots in seconds, uses a fraction of the RAM a VM would reserve, and gives Docker everything it needs to run normally. That's where the bulk of my own containers live, and it's the setup behind services like the Docker/Emby combo on my media lab.
The fastest way to get there is the Docker install script from community-scripts.org (the actively maintained successor to the old tteck helper scripts). Paste one command into the Proxmox shell and it builds a fresh LXC, installs Docker Engine, and hands you the option to add Portainer for a web UI on top. It defaults to a small Alpine container or a slightly larger Debian one, and either can be resized afterward once you know what you're actually going to run on it.
The one setting that trips people up: Docker needs the LXC's Nesting feature enabled (Options → Features in the Proxmox UI), because Docker itself relies on the same kernel namespacing that makes LXC containers work in the first place. Running one containerization layer inside another only works if the outer layer explicitly allows it. The community-scripts.org script sets this for you automatically; if you ever build the container by hand instead, turn Nesting on before installing Docker, not after.
LXC vs VM: When I'd Switch
LXC is my default, but it's not the right call for everything. Docker in an LXC is still, technically, containers running inside a container, and the Proxmox community's own consensus is that anything you'd call "production," or anything you don't want to troubleshoot at 11pm, belongs in a VM instead. A VM gives Docker a real, independent kernel, so it behaves exactly the way its own documentation assumes, with no nesting flag to remember and no shared-kernel edge cases to hit during a Proxmox host upgrade.
My rule of thumb: if losing the service for an afternoon is annoying but not a real problem, it's staying in an LXC. If it's something I'd actually be upset about, like the stack behind my backup and archival routine, it gets a small VM instead. Either way, the guest OS is a standard Debian or Ubuntu install, not a specialized container-only distro like RancherOS or CoreOS; those integrate poorly with Proxmox and with normal config-management tooling, and the extra "purpose-built" layer doesn't buy you anything a regular Debian box running Docker doesn't already do.
One thing that doesn't change either way: never install Docker directly on the Proxmox host itself. It's unsupported, and it means a stuck container can take down the hypervisor managing every other guest on the box, not just the one thing that's misbehaving.
Setting Up Docker Desktop on Windows
Not everything needs to live on the Proxmox cluster. If you're testing a container locally before deploying it, or you just want Docker available on your everyday Windows machine, Docker Desktop is the path of least resistance: it's the actual GUI application (system tray icon, dashboard, settings UI) that bundles the Docker Engine, CLI, and Compose together, and it's built on WSL2 by default now rather than Hyper-V. Before installing, it's worth checking the actual requirements, since a couple of them are easy to miss:
- Windows version: Windows 10 64-bit (Enterprise, Pro, or Education, version 22H2/build 19045 or later) or Windows 11 64-bit (Enterprise, Pro, or Education, version 23H2/build 22631 or later). Windows Server editions aren't supported.
- WSL2: version 2.1.5 or later; if you want Enhanced Container Isolation for extra security between containers, you'll need 2.6 or later specifically.
- Hardware: a 64-bit CPU with Second Level Address Translation (SLAT), at least 8GB of system RAM, and hardware virtualization enabled in the BIOS/UEFI, not just inside Windows.
Installing it is short: grab Docker Desktop Installer.exe from Docker's official Windows install page (it's also listed on the Microsoft Store if you'd rather get updates through there), run it, and pick per-user install unless you specifically need every account on the machine to share one instance. Per-user doesn't need admin rights and is the one Docker itself recommends. On the Configuration page during setup, leave "Use WSL 2 instead of Hyper-V" checked (that's the default and what this guide assumes throughout). Finish the wizard, launch Docker Desktop from the Start menu, and sign in or skip sign-in: the whale icon in the system tray means the engine is up. If you're scripting a fleet of Windows machines instead of doing this by hand, the installer also takes silent flags: "Docker Desktop Installer.exe" install --user for a per-user install, or drop --user and run elevated for an all-users install.
The other thing worth knowing up front, since it has nothing to do with your hardware: commercial use of Docker Desktop at larger companies (more than 250 employees, or more than $10 million in annual revenue) requires a paid subscription. Personal use, education, and small businesses are still covered under the free tier. It's a licensing detail, not a technical one, but it's caught more than a few people off guard after they'd already rolled it out to a whole team.
A Few Things I'd Get Right From the Start
1. Enable Nesting before you install anything
The single most common "Docker won't start" issue in an LXC traces back to this. The community-scripts.org script handles it automatically; a hand-built container needs it set manually first, under the container's Options → Features.
2. Watch for Docker's default bridge colliding with your LAN
Docker's default bridge network uses the 172.17.0.0/16 range. If anything on your existing network already lives in that block, routing gets confusing fast. Worth checking before you deploy anything that needs to talk back out to your LAN.
3. Back up compose files and named volumes separately
A Proxmox snapshot restores the whole guest, but it's not a substitute for keeping your docker-compose.yml files and any named volumes in your actual backup routine. It's the difference between restoring a service and restoring a mystery you have to reverse-engineer.
4. Never install Docker directly on the Proxmox host
Always a guest, LXC or VM, never the hypervisor itself. One misbehaving container shouldn't be able to take the whole cluster's management layer down with it.
5. On Windows, decide WSL2 vs Hyper-V up front
WSL2 is the default backend now and what most current guides and troubleshooting threads assume. Switching backends later after you've got a bunch of containers configured is more of a headache than picking the right one on day one.
50 Common Docker Commands and What They Do
A quick reference for the commands I actually reach for day to day, grouped the same way Docker's own CLI groups them: containers, images, volumes and networks, Compose, and general system maintenance.
Containers
| Command | What It Does |
|---|---|
docker run <image> |
Creates and starts a new container from an image |
docker run -d <image> |
Runs a container in detached (background) mode |
docker run -it <image> bash |
Runs a container interactively with a shell attached |
docker start <container> |
Starts an existing, stopped container |
docker stop <container> |
Gracefully stops a running container |
docker restart <container> |
Stops and starts a container again |
docker pause <container> |
Suspends all processes inside a container |
docker unpause <container> |
Resumes a paused container |
docker rm <container> |
Removes a stopped container |
docker rm -f <container> |
Force-removes a container even if it's running |
docker ps |
Lists running containers |
docker ps -a |
Lists all containers, including stopped ones |
docker exec -it <container> bash |
Opens a shell inside a running container |
docker rename <old> <new> |
Renames a container |
Inspecting & Debugging
| Command | What It Does |
|---|---|
docker logs <container> |
Shows a container's console output |
docker logs -f <container> |
Follows (streams) a container's logs live |
docker inspect <container> |
Shows detailed low-level config and state as JSON |
docker stats |
Shows live CPU, memory, and network usage for running containers |
docker top <container> |
Lists the processes running inside a container |
docker diff <container> |
Shows file changes made inside a container since it started |
Images
| Command | What It Does |
|---|---|
docker pull <image> |
Downloads an image from a registry |
docker push <image> |
Uploads an image to a registry |
docker build -t <name> . |
Builds an image from a Dockerfile in the current directory |
docker images |
Lists locally stored images |
docker rmi <image> |
Removes a local image |
docker tag <image> <new-tag> |
Creates an additional tag for an image |
docker history <image> |
Shows the layer history of an image |
docker save -o <file>.tar <image> |
Exports an image to a tar archive |
docker load -i <file>.tar |
Imports an image from a tar archive |
docker image prune |
Removes unused (dangling) images |
Volumes & Networks
| Command | What It Does |
|---|---|
docker volume create <name> |
Creates a named volume |
docker volume ls |
Lists volumes |
docker volume inspect <name> |
Shows details about a volume |
docker volume rm <name> |
Removes a volume |
docker volume prune |
Removes unused volumes |
docker network create <name> |
Creates a custom network |
docker network ls |
Lists networks |
docker network inspect <name> |
Shows details about a network |
docker network connect <network> <container> |
Attaches a running container to a network |
docker network prune |
Removes unused networks |
Compose
| Command | What It Does |
|---|---|
docker compose up |
Creates and starts every service defined in a compose file |
docker compose up -d |
Starts all services in detached mode |
docker compose down |
Stops and removes the containers and networks that up created |
docker compose ps |
Lists the containers managed by this Compose project |
docker compose logs -f |
Follows logs from every service in the project |
docker compose pull |
Pulls the latest images for all services in the project |
System & Cleanup
| Command | What It Does |
|---|---|
docker system df |
Shows disk space used by images, containers, and volumes |
docker system prune |
Removes all unused containers, networks, and dangling images |
docker system prune -a |
Also removes unused images, not just dangling ones |
docker info |
Shows system-wide Docker configuration and resource usage |
Related Resources
Community Scripts: Docker
The LXC install script this guide is built around.
Docker Desktop for Windows
Official install docs and the full, current system requirements.
Proxmox Forum: LXC or VM?
The community thread this guide's LXC vs VM take is drawn from.
My Media Lab
Docker and Emby running together on the same cluster this guide describes.
Data Hoarding
Where compose files and named volumes fit into a real backup routine.
SFF Proxmox Nodes
Where to start if you don't have a homelab node running yet.
Frequently Asked Questions
Should I run Docker in an LXC container or a VM on Proxmox?
For most homelab services, an LXC container is faster to spin up and lighter on resources, and it's what I use for the majority of my own Debian containers. For anything you'd actually be upset to lose, or that needs to survive a Proxmox host update without babysitting, a VM is the safer default: it's a real kernel, so Docker behaves exactly like it would on bare metal instead of running containers-inside-a-container.
Do I need to enable nesting for Docker to work in an LXC?
Yes. Docker needs the container's Features set to allow Nesting (and usually keyctl) before its storage driver will work correctly, since Docker itself is built on the same kernel namespacing tech LXC uses. The community-scripts.org Docker install script sets this automatically; if you're building the LXC by hand, turn it on first under the container's Options → Features before installing Docker.
What's the easiest way to get Docker running on Proxmox?
The community-scripts.org Docker LXC script. It builds an Alpine or Debian container, installs Docker Engine, and can optionally set up Portainer for a web UI, all from a single command pasted into the Proxmox shell. It's the fastest path from zero to a running Docker host, and it's what I point people to before they try building one manually.
Is Docker Desktop free to use?
For personal use, education, and small businesses, yes. Commercial use at larger companies (more than 250 employees or more than $10 million in annual revenue) requires a paid Docker subscription. That licensing line catches people off guard more often than any technical requirement, so check it before rolling Docker Desktop out at work.
Can I run Docker Desktop on Windows Server?
No. Docker Desktop targets Windows 10/11 specifically and doesn't support Windows Server editions. If you're running a Windows Server box and need containers on it, that's Docker Engine installed directly (with Windows containers) or a Linux VM, not Docker Desktop.
Does Docker actually need a GPU or special hardware?
No, ordinary CPU and RAM are enough for the vast majority of containerized services. The one exception is passing a GPU through to a container for something like Ollama or Plex hardware transcoding, which needs the host (LXC or VM) to have that GPU passed through first, the same requirement as any other GPU workload on Proxmox.