DEV Community

Cover image for No Docker Desktop? WSL2 + Podman on Windows: setup and the errors I hit
cuong do
cuong do

Posted on

No Docker Desktop? WSL2 + Podman on Windows: setup and the errors I hit

Two ways to run containers on Windows without Docker Desktop, plus every red error message I met on the way.

Here is the situation. Your laptop is locked down, Docker Desktop is not on the approved list (or the license is a "talk to finance" thing), and you still need to run docker build before lunch. Good news: you do not need Docker Desktop. Bad news: the two replacements each have their own little traps, and one of them quietly hands you root.

TL;DR

  • Option 1: WSL2 + Docker Engine. Install Ubuntu in WSL, apt install docker.io, done. Feels exactly like Docker. Watch out for systemd and the docker group.
  • Option 2: Podman. No daemon, rootless by default, same commands (alias docker=podman). Watch out for low ports and the Docker named pipe.
  • Security gotcha: "fixing sudo" by joining the docker group gives you root-level power. Rootless Podman and real secrets beat that.

Two ways to run containers on Windows without Docker Desktop

Table of contents

1. Pick your path

Both options use WSL2 under the hood. The difference is who runs the containers.

WSL2 + Docker Engine Podman
Where it runs Docker daemon inside your Ubuntu distro A small Podman machine (a WSL2 distro)
Daemon Yes, dockerd running as root No central daemon
Default user root daemon, you call it via sudo or the docker group Rootless
Commands docker ... podman ... (almost the same)
You run it from The Ubuntu shell PowerShell, CMD or WSL
Best for "I want my Docker workflow back" Locked-down or security-minded setups

My rule of thumb: if your team's scripts are full of docker compose and Docker-only flags, go with Option 1. If you mostly build and run images and your security team frowns at root daemons, go with Podman.

2. Option 1 WSL2 and Docker Engine

This keeps your workflow almost identical to Docker Desktop. You just do the plumbing yourself.

Step 1. Install WSL. Open PowerShell as administrator:

wsl --install
Enter fullscreen mode Exit fullscreen mode

Restart the machine. You need Windows 10 version 2004 (build 19041) or newer, or Windows 11. By default this installs Ubuntu and sets new installs to WSL 2. Check it:

wsl -l -v
Enter fullscreen mode Exit fullscreen mode

You want to see VERSION 2 next to your distro.

Step 2. Install (or pick) a distro. Ubuntu is the default, but you can ask for it by name, and list the others:

wsl --install -d Ubuntu
wsl --list --online
Enter fullscreen mode Exit fullscreen mode

Step 3. Start Ubuntu.

wsl -d Ubuntu
Enter fullscreen mode Exit fullscreen mode

Step 4. Install Docker Engine inside WSL (no Desktop):

sudo apt update
sudo apt install -y docker.io
sudo systemctl enable docker
sudo systemctl start docker
Enter fullscreen mode Exit fullscreen mode

Step 5. Test.

sudo docker run hello-world
Enter fullscreen mode Exit fullscreen mode

If you see "Hello from Docker!", you have a working engine. Notice the sudo though. We will come back to that, because that is where people (me included) take a shortcut with a security price tag.

Pros: same commands, same Dockerfiles, and an easy path to Minikube later. Cons: you manage the engine yourself, and it is a little less smooth than Desktop.

Source: Install WSL

3. Option 2 Podman on Windows

Podman is daemonless: there is no big root process waiting for orders. On Windows, Podman runs inside a "Podman machine", which is a WSL2 distro it manages for you. The podman command in PowerShell talks to it.

Step 1. Install Podman. The official way is the Windows installer from the Podman GitHub releases page. The quick way is winget:

winget install RedHat.Podman
Enter fullscreen mode Exit fullscreen mode

Close and reopen the terminal so podman.exe is on your PATH.

Step 2. Create and start the Podman machine.

podman machine init
podman machine start
Enter fullscreen mode Exit fullscreen mode

If WSL is not installed yet, podman machine init offers to install it for you, reboots, and carries on after you log in. Nice, but do not be surprised by the reboot.

Step 3. Test.

podman run hello-world
Enter fullscreen mode Exit fullscreen mode

If a short image name like hello-world makes Podman ask which registry you mean, give it the full name: docker.io/library/hello-world.

Step 4. Use your Docker muscle memory.

podman build -t myapp .
podman run myapp
alias docker=podman        # in a bash shell
Enter fullscreen mode Exit fullscreen mode

In PowerShell the equivalent is Set-Alias docker podman (add it to your profile to keep it).

Pros: no daemon, rootless by default, Docker-compatible CLI, and security teams like it. Cons: some edge cases with networking and volumes, and Kubernetes integration is a bit more work.

Source: Podman installation, Podman for Windows guide

4. The errors I hit and how to fix them

The fun part. Here is what broke, why, and the fix.

Error 1. wsl --install just prints the help text.
Why: WSL is already installed, so the "install everything" path does not run.
Fix: list what is available and install a distro by name:

wsl --list --online
wsl --install -d Ubuntu
Enter fullscreen mode Exit fullscreen mode

If the download hangs at 0.0%, add --web-download: wsl --install --web-download -d Ubuntu.

Error 2. System has not been booted with systemd as init system (PID 1). Can't operate.
Why: systemctl needs systemd, and some distros or older WSL builds still use the old WSL init. The current Ubuntu from wsl --install has systemd on by default, so you mostly hit this with other distros.
Fix: check your WSL version is 0.67.6 or newer, then add this to /etc/wsl.conf inside the distro:

[boot]
systemd=true
Enter fullscreen mode Exit fullscreen mode

Then restart WSL (see Error 4). Confirm with systemctl status.

Error 3. permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock
Why: the Docker socket belongs to root and the docker group. Your user is in neither, so plain docker ps gets the door slammed.
Fix: add yourself to the group, then restart WSL so the new group sticks:

sudo usermod -aG docker $USER
Enter fullscreen mode Exit fullscreen mode
wsl --shutdown
wsl -d Ubuntu
Enter fullscreen mode Exit fullscreen mode

Then docker ps works without sudo. Here is my lab after the fix: empty table, no error, no sudo.

docker ps works without sudo after usermod and wsl --shutdown

Before you celebrate, read section 5. This fix has a catch.

Error 4. I changed a setting and nothing happened.
Why: WSL only picks up wsl.conf changes after the distro fully stops. Microsoft calls it the "8 second rule": close every shell, then wait about 8 seconds.
Fix: wsl --list --running should say there are no running distributions. Or use the big hammer: wsl --shutdown. It stops all distros, including your Podman machine, so save your work first.

Error 5. Rootless Podman will not bind port 80.
Why: rootless containers cannot bind ports below 1024.
Fix: map to a higher host port (-p 8080:80), which is what I do on a dev laptop anyway. Only if you really need port 80, stop the machine and switch it to rootful:

podman machine stop
podman machine set --rootful
podman machine start
Enter fullscreen mode Exit fullscreen mode

podman machine set --rootful=false takes you back.

Error 6. Docker tools talk to the wrong engine.
Why: Podman listens on the same named pipe Docker clients use by default, npipe:////./pipe/docker_engine. If something else already holds that pipe, the two fight.
Fix: point your tools at Podman's own pipe by setting DOCKER_HOST to npipe:////./pipe/podman-machine-default.

Error 7. podman machine init fails after the automatic WSL install.
Why: the auto-install sometimes gets stuck halfway.
Fix: install WSL manually with wsl --install from an admin PowerShell, reboot, and run podman machine init again. Also check that virtualization is enabled: WSL needs it, and a VM host needs nested virtualization.

Source: WSL config, 8 second rule, systemd in WSL

5. Security gotcha

This is the DevSecOps bit. Read it before you copy any of the fixes above to a shared machine.

  1. The docker group is root with extra steps. Docker's own docs say it plainly: the docker group grants root-level privileges. Anyone in it can start a container that mounts / from the host and edit anything. On your personal lab laptop, fine. On a shared build box, think twice before running usermod -aG docker for everyone.
  2. Rootless is the safer default, so keep it. Podman machines start rootless. --rootful exists, but switching to it just to get port 80 trades a small annoyance for a bigger blast radius. Map to 8080 instead.
  3. Your Windows drives are inside WSL. By default WSL mounts C:\ at /mnt/c. A container started with -v /mnt/c:/host can read your whole user profile, browser data included. Mount only the project folder you need.
  4. Secrets in compose files end up in Git. environment: DB_PASSWORD=SuperSecret123 in a compose file is how passwords travel to a public repo. Keep secrets out of the file: use a .env file listed in .gitignore, or Podman secrets, which are mounted as a file and never baked into an image:
printf 'my-lab-password' | podman secret create db_password -
podman run --secret db_password docker.io/library/alpine cat /run/secrets/db_password
Enter fullscreen mode Exit fullscreen mode
  1. License is a security-adjacent problem too. Docker Desktop is free for personal use and small businesses (under 250 employees and under $10M revenue). Bigger companies need a paid plan. Unlicensed tools on corporate laptops tend to get noticed by the same people who run your security reviews.

Source: Docker post-install steps (docker group warning), podman secret create

6. Checklist

  • [ ] wsl -l -v shows my distro on VERSION 2
  • [ ] systemctl status works inside Ubuntu (systemd on)
  • [ ] docker run hello-world or podman run hello-world prints its hello
  • [ ] I know the docker group equals root, and I only use it on my own lab machine
  • [ ] My Podman machine is still rootless, and I map ports above 1023
  • [ ] I mount project folders, not the whole /mnt/c
  • [ ] No passwords in compose files: .env is in .gitignore or I use podman secret
  • [ ] I run wsl --shutdown knowing it stops every distro, Podman included

Which did you pick on your Windows machine, WSL2 + Docker or Podman? And what was your first red error? Tell me below.

Sources

Top comments (0)