For the last several years, Containers alongside Kubernetes have been an increasingly popular technology for deploying web applications to a variety of hosts. The reasons are many, but application isolation, portability and orchestration are some of the key reasons to "containerize" your web app. When Containers first came onto the scene via Docker, it was really just a Linux-only club. Being an open-source operating system, it was easy to create a scaled-down, super small version of the OS that could be deployed by itself in pure isolation. That, in turn, lent the Docker tooling to be implemented for Linux as well.
Through the years, Microsoft not only revised the Windows Server platform, shrinking its footprint down to bare-bones, allowing it to be a container guest, but also worked closely with the Docker community to allow Windows to be a container host. However, Windows as a container host has generally been a second-class citizen. That's all changed with the Windows Subsystem for Linux (WSL) platform. The platform at it's core is basically a Linux instance running in an abstracted-away version of the Hyper-V virtual machine platform. With the advent of WSL2, which was released in May with Windows version 2004, Docker on Windows can now be considered a first-class citizen for developers! This post will attempt to outline some of the trials, gotchas and benefits of using WSL2 to host Docker containers in development scenarios.
Getting started is normally pretty straight forward. The first thing you will want to do is see if you're running WSL1. The easiest way to check this is by running the command wsl -l -v from a command prompt or PowerShell Window. If you are running WSL1, this command will fail saying that you specified invalid arguments. If you don't have it at all, it will error out saying command not found. If you somehow already DO have WSL2 installed, the command will be successful showing something like this.
The number "2" in the last column of that listing indicates that all of my WSL distros are running on WSL version 2. That is where we want to be, but let's back up to getting our Windows environment running the new WSL2 so we can run that command at all! If, like me, you were already running WSL1, then you can upgrade to the WSL2 platform with a simple command. This is assuming that your Windows 10 machine is capable of running WSL2 in the first place. Simply open an administrative command prompt or PowerShell prompt and paste the following:
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all
At that point, you'll be CAPABLE of running WSL2 enabled distros, but your old one will still be on v1. You can verify that by running the wsl -l -v command and you'll see a "1" rather than a "2" in that final column. Now we're at the first gotcha. It was not easy to find out how to get that default distro upgraded to run on WSL2. Turned out, though it was VERY easy. Another simple administrative command will update that old, default distro to v2.
wsl --set-version Ubuntu 2
It will take a while, but you should now see a "2" when running the wsl listing command (wsl -l -v). At this point, I installed the Docker Desktop application. It was here that I ran into a few more oddities. After the normal install, there's 2 options related to WSL2 that you need to enable, the first is on the "General" screen. Ensure that the "Use the WSL 2 based engine" is checked and enabled.
Simple stuff there. The next step is to go to Resources-WSL Integration and check the "Enable integration with my default WSL distro" setting.
It took me a while to figure out what was going on here since Docker Desktop adds those 2 additional distros to the list (seen above as docker-desktop and docker-desktop-data). The actual Docker images run on the "default" distro, which is specified by the asterisk next to my Ubuntu distro in the listing screenshot above. The Docker Desktop documentation isn't clear exactly on what those 2 docker-desktop machines do, but a great Docker blog post by Simon Ferquel goes into it a little bit. Those are just utility distros that power the Docker Desktop engine on Windows.
WSL2 should be up and running with Docker Desktop! We're ready to "get started". I found the best way to get started with Docker was to follow along with Docker's own getting-started image found on GitHub. It was at this point I ran into the biggest gotcha of them all. As a web developer, you are almost definitely using a web server of SOME kind. I happen to be a Windows developer and I use IIS proper quite a bit. IIS proper runs as a Windows Service, and runs on startup. This is an option for many production-caliber web servers like Apache and NGINX as well. Regardless of the type, if you do have a web server running on startup, it will almost certainly be consuming Port 80. I had it happen to me and got this (not very helpful) error.
Strangely, if Docker itself is responsible for locking port 80, you get a much more friendly message telling you exactly what's wrong. With IIS consuming the port, I was left to debug the message above. Hopefully this helps someone else in their quest to learn Docker on WSL2!
As with any maturing technology, there are a ton of great tools out there for Docker and containers these days! I personally like to use Visual Studio Code alongside the Container Tools Extension to work with Docker in a development environment. We now have WSL2 to work with the existing tooling natively on Windows for a truly first-class development experience!