1. Introduction to WSL

Wikipedia.

Windows Subsystem for Linux (English: Windows Subsystem for Linux, WSL for short) is a compatibility layer for being able to run Linux binary executables (ELF format) natively on Windows 10 and Windows Server 2019.

This means that you can execute Linux programs on Windows with the help of WSL. For developers, this makes a lot of sense.

High-level language development generally relies on a graphical Integrated Development Environment (IDE), so the development environment systems are usually Windows or OSX. OSX was developed from the Unix system, so it comes with a command line terminal, which is developer friendly; while Windows naturally supports graphical operations, and although there are cmd and PowerShell terminals that support simple command lines, they are ultimately limited in functionality and cannot replace Linux functionality.

For example, if you are developing on Windows and need to replace 172.16.12.13 with 141.151.1.111 for all configuration files in a directory and its subdirectories, you don’t know which configuration file contains the string to be replaced and there are many such files scattered around. It would be a lot of work to find it manually on Windows or to write a bat script, whereas on Linux it only takes one command.

1
2
#该命令递归寻找当前目录及子目录后缀是txt的文件并执行替换字符串
find . -type f -name '*.txt' -exec sed -i 's/172.16.12.13/141.151.1.111/g' {} \; 

As you can see, development efficiency would be greatly enhanced if Windows could use Linux system programs.

Microsoft made an attempt to be compatible with Unix like on Windows systems, and first introduced WSL1, which had a big problem with file system performance. Then came WSL2, where the underlying implementation was different from WSL1 and the file system performance was greatly improved. The difference between WSL1 and WSL2 can be found at https://docs.microsoft.com/en-us/windows/wsl/compare-versions.

There are a lot of complaints about WSL on the Internet, which is difficult to use. I personally practice, using WSL2 can have a good development experience, but there are some headaches, here to record some solutions.

1.1 WSL vs Virtual Machine

If you want to run a Linux distribution on a Windows system, you can install a virtual machine before you have a WSL.

Compare a virtual machine with WSL2, where the file system is completely isolated from the host; the latter is interconnected.

WSL2 implements the Linux kernel based on Hyper-v, so WSL is also a complete Linux system. Compared to virtual machines, WSL2 is a bit lighter. But the supported distributions are also limited.

Recommendation: If you have no contact with Linux and want to learn Linux, it is better to install a Linux virtual machine by yourself; and if you are very familiar with Linux, you can try to install WSL2, which will bring better development experience for developers.

2. WSL2 try

For WSL2 installation, please refer to the article: https://dowww.spencerwoo.com/

WSL2 migration reference answer: https://stackoverflow.com/questions/63252225/is-this-the-correct-way-to-import-a-wsl-export-overwriting-default-installati

WSL2 is installed on Windows C drive by default, as the capacity of WSL2 usage becomes larger, it may cause a warning of space on C drive. You can migrate WSL2 to another logical volume using the above method. In fact, WSL, like a virtual machine, is stored in HOST as an image file, and the WSL2-Ubuntu 20 installed on my Win10 already uses 40G of storage, as shown in the figure.

sobyte

If you want to migrate WSL2 from your development environment computer to your home computer, it is also easy to copy the image file away and import it directly to the target machine.

I chose to install WSL2 with Ubuntu 20.04 LTS from the Microsoft Store, and the next steps are based on that Ubuntu distribution.

The WSL boot is to open the corresponding Ubuntu or other distribution installed from the Microsoft Store (as shown below), and the WSL shutdown can be used in PowerShell: wsl --shutdow.

sobyte

2.1 WSL dynamic IP, how to access from outside?

The network of WSL2 is similar to the NAT network mode set in the virtual machine, in this mode the WSL2 instance accesses the external network with the help of the host’s NIC, the host can also access the WSL2 instance, but other hosts in the host’s LAN cannot access the WSL2 instance. As shown in the figure.

The so-called WSL2 instance refers to a certain WSL2 supported distribution installed, I am using Ubuntu 20.04 LTS.

sobyte

The network address of WSL2 changes dynamically (like docker container, the IP address changes on reboot), and no other host on the LAN can access it, which is too inconvenient.

Why is it inconvenient? If you start a service on WSL2 and your colleague can’t access it, it’s very troublesome.

How to solve it? You can map the port of WSL2 to the host win by using Windows port mapping.

The script is as follows.

1
2
3
4
5
6
7
8
#清除网络映射
netsh interface portproxy reset
#获取WSL2实例动态IP
$wsl_ip = (wsl hostname -I).trim().split()[0]
#日志信息
Write-Host "WSL Machine IP: ""$wsl_ip"""
#网络映射win:8080 --> wsl2:8080
netsh interface portproxy add v4tov4 listenport=8080 connectport=8080 connectaddress=$wsl_ip

It can be executed directly in the PowerShell terminal, or it can be saved as a .ps1 script and the script executed in the PowerShell terminal, as follows.

sobyte

2.2 How do I install Docker without installing Docker Desktop?

If you have a virtual machine installed locally, installing docker is easy. However, installing it on a WSL2 instance will take some effort.

The official solution is to install Docker Desktop for Windows on WSL2, you can refer to https://docs.microsoft.com/zh-cn/windows/wsl/tutorials/wsl-containers.

If you don’t want to install Docker Desktop but want to use docker on WSL2, refer to https://dev.to/bowmanjd/install-docker-on-windows-wsl-without-docker-desktop-34m9 for the The solution will be explained in detail next.

Only docker is installed here for WSL2 version, docker is not supported for WSL1 version.

The following configuration is for WSL2 Ubuntu 20.04 LTS for docker configuration, other WSL2 supported distributions have differences in user and permission configuration, please refer to the original article.

2.2.1 Deleting an existing docker

1
sudo apt remove docker-engine docker docker.io docker-ce docker-ce-cli

2.2.2 Installing dependencies

1
sudo apt install --no-install-recommends apt-transport-https ca-certificates curl gnupg2

2.2.3 Ubuntu package repository configuration

Set the os-release related environment variables.

1
2
#执行完成后,可以在shel中执行$ID验证是否存在该变量
source /etc/os-release

Let apt Trusted Warehouse.

1
2
#这里的${ID}是上面source命令执行后的环境变量ID,本示例是:ubuntu
curl -fsSL https://download.docker.com/linux/${ID}/gpg | sudo apt-key add -

Add repository addresses and update the repository list so that apt can use.

1
2
3
#本示例变量替换后的结果为:deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable
echo "deb [arch=amd64] https://download.docker.com/linux/${ID} ${VERSION_CODENAME} stable" | sudo tee /etc/apt/sources.list.d/docker.list
sudo apt update

2.2.4 Installing Docker

Execute the command.

1
sudo apt install docker-ce docker-ce-cli containerd.io

2.2.5 Setting docker command permissions

  1. You can execute with the root user. This is not the norm, for fear of rm -rf / mishaps.
  2. Each time you use sudo docker ..., a normal user using sudo will be operating as the root user. The sudo function is configured in /etc/sudoers for normal users. The WSL2 Ubuntu instance is created with the normal user added to sudoers by default.

In addition to that, you can also add users to a group and give the group the ability to execute a process without secrecy.

1
2
#这里的$USER会解析为当前用户
sudo usermod -aG docker $USER

The docker process has the following password-free configuration in sudoers.

1
2
# sudo visudo, 添加下面
%docker ALL=(ALL)  NOPASSWD: /usr/bin/dockerd

The docker group may have been created by the command that installed docker, so if you go to /etc/group and there is no docker group, you can use the command sudo groupadd -g 999 docker.

In fact, there is a confusion here, because on Ubuntu systems a normal user is given the ability to join a group, and the group can be set up to operate a command as root with no security. If the command involves writing data, you may get a Permission denied error. For example, for git, you need to set sudo chown -R $USER:$USER $GIT_REPO to use it without problems. After checking, the reason may be that the above setting does execute the command as root user, but the result of the command will trigger a new process that is executed as a normal user, so you need to have permissions on the directory.

2.2.6 Configuring dockerd

Set up a directory for the docker socket to use, and set permissions so that the group to which docker belongs has permission to write to.

1
2
3
DOCKER_DIR=/mnt/wsl/shared-docker
mkdir -pm o=,ug=rwx "$DOCKER_DIR"
chgrp docker "$DOCKER_DIR"

To set the dockerd startup parameters, edit /etc/docker/daemon.json and configure it as follows.

1
2
3
4
{
  "hosts": ["unix:///mnt/wsl/shared-docker/docker.sock"],
  "insecure-registries":["a.b.com:5000", "m.n.com:9500"]
}

If there is no corresponding /etc/docker/daemon.json file, you can create it manually. The insecure-registries setting in the parameters means that the insecure http image registry is allowed, and can be configured again if needed.

2.2.7 Starting dockerd

Use the command sudo dockerd to start it. However, to start dockerd in this way, we need to start a container like this.

1
docker -H unix:///mnt/wsl/shared-docker/docker.sock run --rm hello-world

We can start dockerd with a script, which will be easier to use.

2.2.8 dockerd script launch

Start script.

1
2
3
4
5
6
7
8
DOCKER_DISTRO="Ubuntu-20.04"
DOCKER_DIR=/mnt/wsl/shared-docker
DOCKER_SOCK="$DOCKER_DIR/docker.sock"
export DOCKER_HOST="unix://$DOCKER_SOCK"
if [ ! -S "$DOCKER_SOCK" ]; then
    mkdir -pm o=,ug=rwx "$DOCKER_DIR"
    chgrp docker "$DOCKER_DIR"
    /mnt/c/Windows/System32/wsl.exe -d $DOCKER_DISTRO sh -c "nohup sudo -b dockerd < /dev/null > $DOCKER_DIR/dockerd.log 2

Save the script in docker-service under path, in this case in /usr/bin. Execute docker-service to start dockerd.

2.2.9 zsh setup to enable self-starting dockerd

The default sh used by this WSL2 Ubuntu is zsh, so you can set WSL2 to boot dockerd by adding the source /usr/bin/docker-service startup script to /etc/zsh/zprofile.

sobyte

2.3 How do Win and WSL systems interoperate?

2.3.1 File system interoperability

Accessing WSL file system on win

Execute explorer.exe on the wsl instance . , or directly open Windows Explorer and type: \\wsl$\Ubuntu-20.04\opt . As follows.

sobyte

This way to open the wsl file system directory, Windows users have read and write access to the WSL normal user data, for the root user is read-only access. And use this way to open the file modification and save is very laggy, performance problems. Therefore, it is not recommended to modify the contents of wsl instance file system on Windows system .

Accessing the win file system on WSL

WSL2 maps a Windows disk logical volume to a mount file. /mnt/c is the Windows C disk mount path; /mnt/d is the Windows D file mount path and so on and so forth. If you want to open D:\out.txt on a Win system with vim on WSL, you can just use: vim /mnt/d/out.txt.

Operating the Windows file system on WSL will also have some performance issues, but not as severe as the performance delays of Windows operating the WSL file system. If it’s something like a larger git repository, it’s best to clone to the WSL local filesystem operation.

2.3.2 Program call interoperability

WSL is able to read Windows system PAHT variables directly and open them directly on wsl, e.g. ping.exe on WSL: WSL is able to read Windows system PAHT variables directly and open them directly on wsl.

sobyte

There are times when this feature is useful, especially when you open graphical applications. For example, opening a text file in the WSL system with notepad++, etc. Remember that exe programs in the Win system PATH variable are only found in the WSL .

Of course, you can also execute WSL commands on a Windows system, such as wsl ping in PowerShell.

sobyte

The two commands can also be used in combination, for example, in PowerShell: wsl ls -la | findstr "git". For more information, please refer to: https://docs.microsoft.com/en-us/windows/wsl/filesystems

3. Problems with WSL2

3.1 WSL and VirtualBox for Hyper-v conflict

Error: Please enable the Virtual Machine Platform Windows feature and make sure virtualization is enabled in the BIOS.

This is because the Hyper-v service was previously turned off when using VirtualBox. Set Hyper-v mode to be enabled automatically: bcdedit /set hypervisorlaunchtype auto.

After Hyper-v service is started, you need to restart the computer for WSL to start normally.

After restarting the v2ray program, I found that I could not bind to 10809, but I did not find the port occupied by netstat -ano|findstr 10809. I found that the port reserved by the Hyper-v program was probably occupied. The solution is as follows.

1
2
netsh int ip show dynamicport tcp #查看端口范围
netsh int ip set dynamicport tcp start=49152 num=16384 #设置新的端口范围,重启计算机

3.2 Centos6 has problems running on wsl2 docker

There is a problem running containers based on centos6 images on WSL2 docker, solution: add the following configuration to %userprofile%\.wslconfig.

1
2
[wsl2]
kernelCommandLine = vsyscall=emulate