devAlice
← Windows

Docker on Windows — Docker Desktop vs Native WSL2 + License Pitfalls

Two paths for Docker on Windows: Docker Desktop vs installing the docker engine inside WSL2. Cost / performance / license differences.

There are two main paths for running Docker on Windows — Docker Desktop vs installing the docker engine inside WSL2. The deciding factors are company size, licensing, and GUI need.

This guide targets Windows 11 + WSL2 (Ubuntu 22.04+). It is the container-environment decision step after Windows initial setup and WSL tuning.

TL;DR

ItemDocker DesktopNative docker engine in WSL2
License (250+ employees / $10M+ revenue)Paid ($5–21/user/month)Free (open source)
License (personal / small)FreeFree
Installwinget install Docker.DockerDesktop (one line)Manual, 5–10 min
GUI (image/container management)CLI only (or external GUI)
Kubernetes integrationminikube/kind manual
Auto-updateapt/yum manual
Resource isolationDocker manages a dedicated WSL distroSame as your usual WSL Ubuntu
Recommended forIndividuals / SMB / GUI neededCompany license avoidance / CLI-only

Decision Tree

Company has 250+ employees OR $10M+ revenue?
   │
   ├─ Yes → confirm Docker Desktop license (subscribe or WSL2-native)
   │
   └─ No →
       Need GUI / one-click Kubernetes?
          │
          ├─ Yes → Docker Desktop
          │
          └─ No → Native docker engine in WSL2 (lightest)

Prerequisites

  • Windows 10 build 19041+ or Windows 11
  • WSL2 enabled — WSL tuning
  • Virtualization on (VT-x / SVM enabled in BIOS)

Path A — Docker Desktop — 5 min

The common path. UI + Kubernetes + WSL integration come in one shot.

A.1 Install

winget install Docker.DockerDesktop

One restart after install.

A.2 WSL2 Backend

Launch Docker Desktop → Settings → General → Use the WSL 2 based engine ✅ (default).

A.3 WSL Distro Integration

Settings → Resources → WSL Integration → enable your distro (Ubuntu) ON.

Now docker works inside WSL Ubuntu:

# Inside WSL Ubuntu
docker --version
# Docker version 24.x.x, build xxxxx
docker info
docker run --rm hello-world

A.4 Resource Limits

Settings → Resources → memory/CPU sliders. Default is 50% of host. For laptops, 4GB / 2 CPU is plenty.

// .wslconfig (separate from Docker Desktop — controls all WSL resources)
[wsl2]
memory=8GB
processors=4
swap=2GB

A.5 License — the biggest gotcha

Free use conditions:

  • Personal use
  • Education / research
  • Non-profit
  • Company fewer than 250 employees AND under $10M annual revenue

If none apply, a paid subscription is required:

PlanPriceNotes
Personal$0If you meet free-use conditions
Pro$5/moIndividual paid
Team$9/moSmall teams
Business$24/mo250+ companies

For commercial use, confirm with your IT team. To avoid: Path B.


Path B — Native docker engine in WSL2 — 10 min

License avoidance + lightweight. No GUI.

B.1 Install docker inside WSL Ubuntu

# Inside WSL Ubuntu (22.04+)
 
# 1. Remove conflicting packages
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do
  sudo apt-get remove -y "$pkg" 2>/dev/null
done
 
# 2. Add Docker's official repository
sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo 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/ubuntu \
  $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
 
sudo apt-get update
 
# 3. Install docker engine + compose plugin
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

B.2 Enable systemd (off by default in WSL2)

WSL2 doesn't use systemd by default → docker daemon won't auto-start. Enable:

# Edit /etc/wsl.conf (requires sudo)
sudo tee /etc/wsl.conf > /dev/null <<'EOF'
[boot]
systemd=true
EOF

Restart WSL from Windows PowerShell:

wsl --shutdown
# Then re-enter wsl

B.3 Add User to docker Group — Run Without sudo

sudo groupadd docker
sudo usermod -aG docker $USER
# New shell (or wsl --shutdown + re-enter)
newgrp docker
 
# Verify
docker run --rm hello-world

B.4 Confirm Auto-start

systemctl is-enabled docker     # enabled
systemctl status docker         # active (running)

Docker daemon auto-starts on every WSL launch.


Path C — Podman (alternative) — 5 min

Docker-compatible + daemonless + free. A common choice to avoid corporate license issues.

# Ubuntu 22.04+
sudo apt-get install -y podman podman-compose
 
# Alias docker to podman (optional)
echo 'alias docker=podman' >> ~/.bashrc
echo 'alias docker-compose=podman-compose' >> ~/.bashrc

Most Dockerfile and docker-compose.yml work as-is. Caveats:

  • Rootless by default — some host-networking restrictions
  • Docker Hub isn't set as default → add to ~/.config/containers/registries.conf

Out of scope for this guide — separate guide candidate.


1. Performance Comparison — Measured (Ubuntu 22.04 + WSL2)

Same machine (16GB RAM, Ryzen 7), 100 runs of docker run --rm node:20 npm install:

MethodTime (cold cache)Idle memory
Docker Desktop4.8s~1.2GB (Docker Desktop process)
WSL2 native4.6s~150MB (dockerd only)
Podman4.7s~80MB

CPU/disk performance is nearly identical. The big delta is idle memory — native/Podman are kinder to laptop batteries.


2. Daily Patterns

2.1 One-line docker run aliases

# ~/.bashrc or ~/.zshrc
alias dps='docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}"'
alias dim='docker images --format "table {{.Repository}}:{{.Tag}}\t{{.Size}}"'
alias dprune='docker system prune -af --volumes'  # careful!

2.2 Faster Compose

# Rebuild + restart only changed services
docker compose up -d --build app
 
# Force image cache reuse
DOCKER_BUILDKIT=1 docker compose build

2.3 docker engine inside WSL Ubuntu + IDE on the Windows host

  • Open the WSL folder via VS Code Remote-WSL
  • VS Code's Docker extension auto-detects the daemon inside WSL
  • Build/run inside WSL, edit in the Windows IDE

Almost the same UX as Mac iTerm + Docker Desktop, license-free.

2.4 Cleanup You'll Use Often

docker system df              # disk usage
docker container prune        # remove stopped containers
docker image prune -a         # remove untagged images
docker builder prune          # clear buildkit cache

3. WSL2 → Docker Disk Location (occasionally bites)

WSL2's data lives inside an ext4.vhdx virtual disk. Over time, it grows and doesn't auto-shrink.

Compact Disk (manual)

# Windows PowerShell (admin)
wsl --shutdown
 
# Compact the vhdx — Ubuntu example
$vhd = "$env:LOCALAPPDATA\Packages\CanonicalGroupLimited.Ubuntu_79rhkp1fndgsc\LocalState\ext4.vhdx"
Optimize-VHD -Path $vhd -Mode Full
# Without Hyper-V, use diskpart for the equivalent

Often docker-side cleanup alone is enough (docker system prune -af --volumes).


4. Troubleshooting

"docker: Cannot connect to the Docker daemon"

  • Path A: Docker Desktop not running. Launch from Start menu and wait.
  • Path B: systemd disabled or daemon not started. sudo systemctl start docker.

"permission denied while trying to connect to Docker daemon socket"

User not in docker group. sudo usermod -aG docker $USER + newgrp docker, or a new WSL session.

Native WSL docker conflicts with installed Docker Desktop

Both running on the same WSL distro conflicts. Pick one:

  • Desktop → leave that distro checked in Settings → Resources → WSL Integration
  • Native → uncheck and quit Desktop

Image builds are slow

  • Confirm BuildKit: export DOCKER_BUILDKIT=1
  • Add node_modules / .git to .dockerignore — context size hits build time directly
  • Multi-stage builds + cache mounts (RUN --mount=type=cache,target=/root/.npm)

Windows filesystem mounts are slow

/mnt/c/... over 9P is slow. Work inside the WSL ext4 area (~/). For frequent Windows↔WSL file exchange, use \\wsl$\Ubuntu\... or VS Code Remote-WSL.


Next Steps

References

Changelog

  • 2026-05-12 — Initial draft (devAlice M2 seed expansion)

Comments