Set up Docker from scratch on WSL 2
Just recently Microsoft released its latest update to Windows and with it comes an update to WSL. Previously it was using a translation layer that translated Linux system calls into NT system calls. This allowed running unmodified native ELF binaries directly under Windows albeit with some restrictions. It’s exactly those restrictions that made it impossible to run Docker natively on the subsystem. The reason for this is that for a good chunk of the API’s to make namespaces, cgroups, … work the implementation just wasn’t there and seemed non-trivial to implement. This all changed as of WSL2 as Windows now ships with a full-fledged Linux kernel, using virtualization technologies to improve file system performance and adding full system call compatibility.
To get Docker running natively under this recent version, you can just install the latest Docker for Windows. The installer will guide you through the process and offer the option to use docker under WSL 2. The process is straightforward and from my experience, it makes using docker under Windows even more reliable and giving it that native feeling. The way it works is that the installer will create a new WSL instance under which it installs the whole docker toolchain. You can have a peek at this by running wsl -l -v
which should print something similar like the following:
It’s those docker-desktop*
instances that will host docker and any containers or images. There is a flag buried in the Docker for Windows
settings menu that allows you to expose this same docker environment to your other WSL instances. Settings>Resources>WSL Integration
has a toggle for each WSL instance. The way this works is that it will add a few binaries to that WSL instance and a proxy that forwards any requests.
But what if you want to run and manage your own setup without using Docker on Windows
. Well, that’s possible too! Remember we are running on a full Linux kernel now. So, for whatever distro you are using now, you can follow the standard docker installation instructions for that distribution. I’m using Ubuntu so let me walk you through the process of setting this up. If you are running another distro have a look at the docker documentation here: https://docs.docker.com/engine/install/
Installation
First let’s update our packages and install some dependencies that are required in order to get docker up and running.
Next, we will need to grab the official docker PGP key.
Have a look at the official docker installation docs to help you in verifying that the key you just installed is the correct one. It just boils down to this:
Run the following command to get the docker repository set up:
Ok, that’s all the setup and preparation work we needed to get done. Now let’s get our hands dirty and install docker. If you prefer to install a specific version, then have a look at the official docs again. Those will explain what you need to change to the following command to install that specific version.
During the installation process it will ask to configure and setup grub. You can safely skip this procedure because the WSL Linux kernel doesn’t use grub.
At this point, we should have docker installed and available to use, we can verify this by running the following commands:
We can see that we have docker installed, but when running it we get an error message saying that we can’t connect to the Docker daemon. WSL doesn’t use systemd so docker won’t be able to start on its own. We will need to start the daemon manually by using the following command:
After this, the last thing you need to do is to add your current user to the docker group. This will allow you to use the Docker cli without typing sudo
For this to take into effect we will need to restart our instance wsl --terminate name-of-wsl-distro
or wsl --shutdown
(caution this last one will shut down all your WSL instances).
You will notice that when you restart your WSL instance the docker daemon is not automatically started again. At the moment there isn’t a recommended way to start the daemon on boot. The current recommendation https://github.com/microsoft/WSL2-Linux-Kernel/issues/30#issuecomment-558241868 is to launch the daemon in your .bashrc
We will need to edit the sudoers
file with sudo visudo
and add the following line at the bottom of the file, replacing username
with the name of your current user.
Then in your .bashrc
file you can add to the following to start the service when it’s not running yet.
Putting it all together
You should be all set up now, let’s try a few commands to check whether our setup is working. The default docker installation guides you into running the hello-world
image, so let’s give that a try:
If you get a similar result as the one above, then that means everything is working. But let’s take it one step further and see if we can build an image and get a webserver up and running. Paste the following into a Dockerfile
Then in the same directory as where you created this Dockerfile
plug the following commands in your terminal docker build -t hello-world-aspnet .
and docker run -it -p 5000:5000 hello-world-aspnet
. You should now have an ASPNET Core web app running on port 5000:
Congratulations you now have Docker running natively under WSL 2 on a Linux kernel that’s shipped with Windows 🤯.
Summary
In this post, I talked about what changed in WSL 2 to make docker run on this subsystem. To then go through the Docker for Windows setup process briefly, how you can get it running on WSL and how this works internally. I also showed you how to get docker up and running from scratch onto a new WSL instance. How to overcome any issues you might face when installing it from scratch and having it automatically start up when your WSL instance boots. This process can be scripted to save you time on your next setup and with help of wsl --export
you can easily create an export that can be used as a backup.