Running Docker on Windows has been easy for a long time, but it has always needed to run inside a Hyper-V virtual machine. There are at least two, and probably more, problems with this approach:

  1. Hyper-V requires Windows Professional, a ludicrous limitation, which made docker (and lots of other great tools) unavailable to Windows Home users.
  2. The CPU and memory resources allocated to the Hyper-V VM and therefore to your docker containers must be managed by you.  Assign too many and you'll lose access to those resources from your Windows OS, assign too few and you'll see performance issues in your containers.

Thanks to the Windows Subsystem for Linux 2 though it's now possible to run docker in a WSL distribution and avoid the need for Hyper-V altogether.

Stuff you'll need

  1. Windows 10 Build 19041 or later.
  2. Docker desktop version 2.2.0.5 or later.
  3. WSL 2 installed.

Before using WSL

By default, docker desktop currently uses Hyper-V which means if you install it today and start it up, behind the scenes it will spin up a VM. If you run Get-VM from PowerShell you can see that VM has the rather un-mysterious name DockerDesktopVM.

Get-VM

In my case docker has assigned 2GB of memory to the VM and if I run Get-VMProcessor I can see that my docker VM has two processors assigned.

Get-VMProcessor

And if I run docker info I can see that those are the resources available to my docker server.

docker info

If I open up docker desktop Settings->Resources tab, I'll see the same settings and from here I can manually configure those available resources.

Settings -> Resources

Enable Docker WSL

So that's a quick overview of how things work running docker in Hyper-V, now let's see how things are different with WSL. To enable the WSL engine, I just need to go to Settings -> General and turn on Enable the experimental WSL 2 based engine.

Settings -> General

Once I Apply & Restart docker will restart and my DockerDesktopVM will no longer be running.

Now instead I have two WSL distros running which I can see by running wsl -l -v.

Two distros ... that's seems strange, why does docker use two WSL distros when it only needs one Hyper-V VM? The name is giving us a clue, the docker-desktop-data distro exists as a storage for images and configs, as well as the Kubernetes data store. Those are used by the docker-desktop distro, the same result is achieved when docker is run under Hyper-V by mounting a VHD (Virtual Hard Disk) in the Hyper-V image but mounting a VHD isn't possible with WSL2 yet.

But moving on to more exciting news let's run docker info.

docker info

Now I can see that docker has access to 8 CPU cores and 13GB of the 16GB installed in my laptop. Because docker is now running in a WSL distro it gets access to all the CPU cores and by default 80% of the RAM. This is the shared across all distros running under WSL 2 and the allocation of resources will be handled dynamically for you by WSL.

If you want to modify config settings for WSL 2 to explicitly limit the available resources you can do that by creating a .wslconfig file inside your user profile directory and setting any/all of the parameters below. Personally, though I've found that just leaving WSL alone to manage these for me has worked pretty smoothly.

[wsl2]
kernel=<path>              # An absolute Windows path to a custom Linux kernel.
memory=<size>              # How much memory to assign to the WSL2 VM.
processors=<number>        # How many processors to assign to the WSL2 VM.
swap=<size>                # How much swap space to add to the WSL2 VM. 0 for no swap file.
swapFile=<path>            # An absolute Windows path to the swap vhd.
localhostForwarding=<bool> # Boolean specifying if ports bound to wildcard or localhost in the WSL2 VM should be connectable from the host via localhost:port (default true).

# <path> entries must be absolute Windows paths with escaped backslashes, for example C:\\Users\\adamc\\kernel
# <size> entries must be size followed by unit, for example 8GB or 512MB
.wslconfig

Accessing docker from another WSL distribution

Navigating to Settings -> Resources in docker desktop now that WSL integration is enabled I see can see that there's no longer an Advanced tab for configuring docker resources, which makes sense given what we've just talked about. I also see that there's a new setting available for WSL Integration.

WSL Integration

In this case I've installed an Ubuntu distro from the Windows store, but you might see different distros listed or even none. If you don't see any listed even though you have a distro installed, you'll need to upgrade your distro to WSL 2. Toggling this switch and then hitting Apply & Restart install the docker client tools in my Ubuntu distro and give it access to the docker server running inside my docker-desktop distro.

If I launch my Ubuntu distro and run docker info I can see that I have access to the same server that's available to me from Windows.

For a fun way to prove that I can run a container from inside Ubuntu.

Switch to Powershell in Windows and when I list my docker containers there I'll see the exact same container running.

Wrapping up

In summary, for me the new WSL backend for docker makes docker so much nicer to work with on Windows. I get all the performance I need along with sweet integration across Windows and any Linux distributions I have installed. On top of this docker now gets the ability to run on Windows Home, Microsoft have made that impossible for far too long but this a very welcome change.

If you want to find out more about the details of the docker desktop WSL 2 backend I thoroughly recommend Introducing the Docker Desktop WSL 2 Backend on the docker blog.