How to Install and Configure WSL2 and Docker for Windows and run Dev-Containers on top of them.

Expanded and detailed tutorial on how to install Windows Sub-System for Linux (WSL2), and Docker for windows, including explanation on how to run Dev-Containers on top of it, configuring them and developing in a container environment.

Introduction

In May 2020 Microsoft introduced a new way of running native Linux based applications on Windows which is called WSL2 — Windows Sub-System for Linux. This technology was introduced in version 2004 (build 19041) of Windows 10. WSL2, unlike its predecessor WSL, is a full Linux kernel capable of running on top of your Windows system. The arrival of WSL2 is game-changing and it allows us to run windows and Linux on the same OS without the need of running dual boot systems or a virtual machine with a Linux distribution.

Installing WSL2

First thing thing we need to do is to check if our Windows release version supports WSL2. Click Winkey + R and type ‘winver’ and the following window will pop up:

If you have version 2004 or 20H2 you are good to go!

IMPORTANT! Microsoft have recently announced that WSL2 distros are being backported to Windows 10 version 1903 and 1909! so if have one of these versions you should be fine as well.

First, we need to install WSL, upgrade it to WSL2 and set it to be the default version. Open a PowerShell as an administrator, this option grants the program permission to make changes to files, system settings, and registry settings. Run the following commands, each command must be executed separately by pressing the Enter/Return key in the PowerShell after each paste operation. The official Microsoft instructions can be found here.

Inside Powershell type:

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

Now we have WSL enabled in our system, next we insert the following command:

dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

This is a feature allows applications to use virtual machines which allows WSL2 to use virtualization. Before we proceed we have to restart our system.

After restarting our system we need to install the WSL2 Linux kernel update package for x64 machines. After the installation is complete, open PowerShell as administrator if it is not open yet and type:

wsl --set-default-version 2

This sets WSL 2 as the default version when installing a new Linux distribution. Congrats! we have WSL2 installed on Windows.

Installing a Linux Distribution

You can now open the Microsoft Store and type “Linux” in the search box. I recommend installing Ubuntu 18.04. I’ll be using this version so if you choose another distribution some of the steps ahead might be different.

Select Ubuntu 18.04 LTS from the Microsoft Store and click on “get” which will install this distribution on your system.

You can find the installed app in the list of installed programs in the start menu, or just type ‘ubuntu’ in search box near the start menu button. when inside the installed distribution wait a few seconds for the installation to complete and than insert your username and password.

Now to make sure everything is updated, copy and paste the following command, you will be asked to type your password afterwards.

sudo apt update && sudo apt -y upgrade

Open the PowerShell as administrator the following commands:

PS C:\WINDOWS\system32> wsl --set-version Ubuntu-18.04 2
PS C:\WINDOWS\system32> wsl -l -v

You should see the following list:

Our ubuntu distro is now configured to run with WSL2!

Installing Docker for Windows

If you are not familiar of what Docker is, you can read about it more in depth here. In short, Docker is a tool which allows us to run our applications in isolated environments called containers, the main advantages of Docker are:

  • It is a tool used to package our application with all it’s dependencies, deploy and run it.
  • Containers allows us to run applications independently of the environment hosting them.
  • Containers are isolated from one another and allow us an easy configuration and smooth deployment process.

Docker for windows can be downloaded here. When installing make sure the “Install required Windows components for WSL2” is checked. After completing the installation you will be requested to log out of Windows. Login and you will see that docker is starting in the background, if you open PowerShell and type:

PS C:\Users\alex> wsl -l -v
NAME STATE VERSION
* Ubuntu-18.04 Running 2
docker-desktop-data Running 2
docker-desktop Running 2

You should see all three in Running state, if your Ubuntu distribution is in stopped state for some reason, just find it the list of your installed applications and run it.

Configuring docker

By this stage you will have a docker icon in your system tray, right click on it and press on the ‘Settings’ option will get you to this screen:

Make sure the ‘Use the WSL 2 based engine’ is checked, now click on the ‘Resources’ option and on the ‘Network’ option. Here there is the possibility to change default DNS server, for example if you want to use your organization’s DNS server. Next, click on the ‘WSL Integration’ option and you will ses the following screen:

Enable both of the options and click the ‘Apply & Restart’ button. This is very important and it allows docker containers to run on your installed Linux Distribution.

That’s it, Docker for Windows is configured and ready to run containers. You are probably wondering how we can actually run and develop your application after all we have done so far. So the next step is putting our projects inside the Ubuntu directory and running them.

Configuring the installed Linux Distro

In order to get to the files of your installed Distro click Winkey + R and type:

\\wsl$

press ‘Enter’ and you will see three folders, two of the are Docker folders and one of the is ‘Ubuntu-18.04’ which contains the all the system files of the Ubuntu installed distro. At this point, I recommend mapping the current directory as a Network Drive in your system.

If you have done everything correctly you should have a Mapped Network Drive (Z:\) which points to your installed Linux Distro main directory. Navigate to that folder and than to home/<your user name>. This is your User’s home directory and where you should place your projects to be able to run them in a Linux environment. Here we create a projects directory where all of our projects will be stored. Now lets create our first project:

  1. Install the following VS Code extensions:
  1. Open VS Code and click the “F1” button to get to the command prompt — select the Remote WSL — New Window using Distro option.
  2. Select Ubuntu-18.04 — VS Code is now running from within our Ubuntu home directory.
  3. Copy or Create a project —in this tutorial we will create a test project. Navigate to home/<your user>/projects and create a folder named test.
  4. Go back to VS Code and open the folder we have just created. The next step is to initialize a project — notice if you try and type npm init you will get an error from the terminal saying “Command ‘node’ not found”. This is because we currently do not have Node installed inside Ubuntu. This is where Docker comes into the picture.

Lets summarize everything we have done so far!

  • We have an installed Linux Distribution installed — Ubuntu 18.04.
  • We Installed Docker For Windows — and configured it to be able to work with WSL2.
  • We Mapped the base folder as Network drive Z:\.
  • VS Code has all the required Extensions installed in order to run and work with Containers.

Run and Code inside a Dev-Container

Dev container is basically a container which combines a development environment with all the benefits of a container, and while dev containers can seem complicated, in practice they are actually very simple.

The Dev container will have all the dependencies our project require: NodeJS, git, npm etc. We will use our VS Code instance to connect to a remote environment which is dev-container running on top of Ubuntu. To simplify, our code is mounted inside the container and via the WSL network we can connect through VS Code to that container instance and code inside it!

Getting back to our open VS Code window, we should have the test folder open. now press F1 and choose the following option:

Remote-Containers: Open Folder in Container...

Choose the type of framework you would like to write your code — in our case we Choose Node.js. Wait a few seconds for the NodeJS based image to be built and the container should open if no errors occurred. There are two files now in our project — devcontainer.json and Dockerfile.

devcontainer.json — contains all your exposed ports, mounted resources and other configuration optionsInformation about devcontainer.json options can be found here. Lets create a small app that listens on port 5000 and get a response from it.

  1. Type npm init— to create a project.
  2. Install the express and body-parser packages.
  3. Create a small app which listens on ports 5000 and have an API end point with the “/” path.
const express = require('express');
const bodyParser = require('body-parser');
let app = express();const port = 5000;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.listen(port, function () {
console.log(`Server running on port: ${port}`);
});
app.get('/', (req,res) => {
return res.status(200).send('OK');
});

4. Open the devcontainer.json file and change the the forwardPorts property:

"forwardPorts": [5000]

5. Port is now forwarded and is open to requests from the localhost network.

6. Press F1 to open the command prompt again and choose the Remote-Containers: Rebuild Container option to rebuild the container with the updated settings.

7. Run the app.

In order to send requests to this app — we need to get the IP address of the WSL network — this can be done by opening the CMD and typing ipconfig.

Send a GET request with Postman to the address you get with port 5000 and you should get a response. This is it, our app is now running in a dev-container running in a Linux distribution inside Windows.

Dev containers enables us to develop on the same environment we will have on production, and while there are still issues regarding support for certain features and dependencies, the benefits definitely outweigh the issues.

Thank you for Reading!

Fullstack Developer at Bis-Tec technologies