banner

Custom WSL Distros

Last updated 

Introduction

Windows Subsystem for Linux (WSL) is essentially a specialized container platform - particularly WSL2, which uses a shared, virtualized Linux kernel to run each WSL distro. (The kernel is open source and can be found on Github). In fact, even Docker Desktop uses the WSL2 kernel to run Linux containers on Windows if it's installed.

WSL distros are essentially long-lived containers (e.g., their filesystems are not removed when the container process terminates), which makes them particularly useful as development environments.

Build Process

Microsoft has a good guide for building custom distros here, but I've developed what I believe to be an even easier process - mostly because I've fully scripted out every necessary command.

Create a Dockerfile

Custom distros are typically created from Docker containers. For maximal efficiency, I recommend using a Dockerfile. I use the following example to create a development environment for Packer plugins.

FROM golang:1.21.4-bookworm

RUN apt update && apt upgrade -y; \
    apt install git vim dos2unix curl wget iproute2 iputils-ping gnupg \
		software-properties-common netcat-traditional lsof procps iptables \
		strace -y; \
    wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | \
        tee /usr/share/keyrings/hashicorp-archive-keyring.gpg; \
    echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | \
        tee /etc/apt/sources.list.d/hashicorp.list; \
    apt update && apt install packer terraform -y; 

COPY bashrc /root/.bashrc

Note that the example assumes you have a bashrc file in the same directory as your Dockerfile.

Create WSL Distro

Once you've created your Dockerfile, simply adjust the variables at the top of the following PowerShell script and copy/paste your way to a new WSL distro.

# adjust these variables:
$imageName = "BUILD_NAME"
$imageVersion = "1.0"
$dockerUsername = "YOUR_DOCKER_USERNAME"
# build the container
$tag = [string]::Format(
	"{0}/{1}:{2}",
	$dockerUsername, $imageName, $imageVersion
)
# from the same directory as your DOCKERFILE:
docker build -t $tag .
# export the container
$tarPath = "$env:temp/$imageName.tar"
docker export $(docker create $tag) --output=$tarPath
# import as a wsl distro - store within LOCALAPPDATA
$wslDir = "$env:LOCALAPPDATA\wsl\$imageName"
New-Item -ItemType Directory -Path $wslDir -Force
wsl.exe --import $imageName $wslDir $tarPath
# clean up export
Remove-Item -Path $tarPath
# open the distro
wsl -d $imageName