Wednesday, 29 April 2026

SONiC Part 1: SONiC Lab Setup on Windows (Step-by-Step)

 

Introduction

 

This chapter explains how to build a SONiC virtual test environment on a Windows computer. First, we enable the required Windows features for WSL 2 and update and verify the WSL installation. Next, we install an Ubuntu distribution and validate that the Linux environment is working correctly, including basic resource checks (CPU, memory, and disk). After the Linux environment is ready, we install Docker Engine from Docker’s official repository and complete the required post-installation steps to run containers. We then install Containerlab, download the SONiC virtual switch image (docker-sonic-vs.gz), copy it into WSL, and load it into Docker. Finally, we install Visual Studio Code on Windows and connect it to WSL to make creating and editing the YAML topology files easier. The next chapter uses this environment to define and deploy a simple SONiC-based topology.



Phase 1: Enable Features for WSL



WSL 2 requires two Windows features to be enabled. The first feature, Microsoft-Windows-Subsystem-Linux (Example 1-1), enables WSL. The second feature, VirtualMachinePlatform (Example 1-2), is required to run WSL 2.

In this example, both features are enabled using Microsoft PowerShell (Run as Administrator) with the dism.exe command. The options used are:

·         /online: Applies the changes to the running operating system

·         /enable-feature: Specifies that a Windows feature is being enabled

·         /featurename: Specifies the name of the feature

·         /all: Enables all parent features required by the selected feature

·         /norestart: Prevents an automatic restart after the operation

 PS C:\WINDOWS\system32> dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

 

Deployment Image Servicing and Management tool

Version: 10.0.26100.5074

 

Image Version: 10.0.26200.8246

 

Enabling feature(s)

[==========================100.0%==========================]

The operation completed successfully.

PS C:\WINDOWS\system32>

Example 1-1: Enable WSL in PowerShell.

PS C:\WINDOWS\system32> dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

 

Deployment Image Servicing and Management tool

Version: 10.0.26100.5074

 

Image Version: 10.0.26200.8246

 

Enabling feature(s)

[==========================100.0%==========================]

The operation completed successfully.

PS C:\WINDOWS\system32>

Example 1-2: Enable Virtual Machine Platform in PowerShell.


Phase 2: Install WSL



Before installing a Linux distribution, update the WSL platform (kernel and supporting components) by running wsl --update.

 

PS C:\WINDOWS\system32> wsl --update

Downloading: Windows Subsystem for Linux 2.6.3

Installing: Windows Subsystem for Linux 2.6.3

Windows Subsystem for Linux 2.6.3 has been installed.

The operation completed successfully.

Checking for updates.

The most recent version of Windows Subsystem for Linux is already installed.

Example 1-3: Update WSL.

We can verify the installed WSL components and the Linux kernel version by running wsl --version. The output includes WSLg (graphics support for Linux GUI apps) and MSRDC (Microsoft Remote Desktop Client), which are used when running Linux GUI applications (for example, a GUI web browser such as Firefox) through WSL. The output also shows DXCore and Direct3D versions, which relate to GPU acceleration, as well as the Windows build version of the host OS.

 

PS C:\WINDOWS\system32> wsl --version

WSL version: 2.6.3.0

Kernel version: 6.6.87.2-1

WSLg version: 1.0.71

MSRDC version: 1.2.6353

Direct3D version: 1.611.1-81528511

DXCore version: 10.0.26100.1-240331-1435.ge-release

Windows version: 10.0.26200.8246

Example 1-4: Verify the WSL version.

 

Phase 3: Install a Linux Distribution



After updating the WSL platform, we use the wsl --list --online command to see which Linux distributions are available online.

 

  

PS C:\WINDOWS\system32> wsl --list --online

The following is a list of valid distributions that can be installed.

Install using 'wsl.exe --install <Distro>'.

 

NAME                            FRIENDLY NAME

Ubuntu                          Ubuntu

Ubuntu-24.04                    Ubuntu 24.04 LTS

Ubuntu-22.04                    Ubuntu 22.04 LTS

Ubuntu-20.04                    Ubuntu 20.04 LTS

openSUSE-Tumbleweed             openSUSE Tumbleweed

openSUSE-Leap-16.0              openSUSE Leap 16.0

SUSE-Linux-Enterprise-15-SP7    SUSE Linux Enterprise 15 SP7

SUSE-Linux-Enterprise-16.0      SUSE Linux Enterprise 16.0

kali-linux                      Kali Linux Rolling

Debian                          Debian GNU/Linux

AlmaLinux-8                     AlmaLinux OS 8

AlmaLinux-9                     AlmaLinux OS 9

AlmaLinux-Kitten-10             AlmaLinux OS Kitten 10

AlmaLinux-10                    AlmaLinux OS 10

archlinux                       Arch Linux

FedoraLinux-43                  Fedora Linux 43

FedoraLinux-42                  Fedora Linux 42

eLxr                            eLxr 12.12.0.0 GNU/Linux

OracleLinux_7_9                 Oracle Linux 7.9

OracleLinux_8_10                Oracle Linux 8.10

OracleLinux_9_5                 Oracle Linux 9.5

openSUSE-Leap-15.6              openSUSE Leap 15.6

SUSE-Linux-Enterprise-15-SP6    SUSE Linux Enterprise 15 SP6

PS C:\WINDOWS\system32>

Example 1-5: List available Linux distributions.

The latest available Ubuntu-24.04 distribution is used in this lab. A new Unix user account is created during the installation process.

 

PS C:\WINDOWS\system32> wsl --install -d Ubuntu-24.04

Installing: Ubuntu 24.04 LTS

Distribution successfully installed. It can be launched via 'wsl.exe -d Ubuntu-24.04'

Launching Ubuntu-24.04...

Provisioning the new WSL instance Ubuntu-24.04

This might take a while...

Create a default Unix user account: nwkt

New password:

Retype new password:

passwd: password updated successfully

To run a command as administrator (user "root"), use "sudo <command>".

See "man sudo_root" for details.

Example 1-6: Install Ubuntu 24.04.

After installing the Ubuntu 24.04 distribution, we can start it from Windows PowerShell by running wsl (or wsl -d Ubuntu-24.04). By default, the shell often opens under /mnt/c/Windows/System32. Before running further commands, we change to the Linux home directory with cd ~ (or simply cd). Working under the mounted Windows system directory is discouraged: it is protected by Windows permissions and is not a suitable location for creating project files.

Next, run cat /etc/os-release to verify details of the installed Ubuntu distribution.

PS C:\WINDOWS\system32> wsl

 

PRETTY_NAME="Ubuntu nwkt@Toni:/mnt/c/WINDOWS/system32$ cd ~

nwkt@Toni:~$ cat /etc/os-release

24.04.4 LTS"

NAME="Ubuntu"

VERSION_ID="24.04"

VERSION="24.04.4 LTS (Noble Numbat)"

VERSION_CODENAME=noble

ID=ubuntu

ID_LIKE=debian

HOME_URL="https://www.ubuntu.com/"

SUPPORT_URL="https://help.ubuntu.com/"

BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"

PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"

UBUNTU_CODENAME=noble

LOGO=ubuntu-logo

Example 1-7: Verify the Linux distribution.

You can also run lsb_release -a command (lsb-Linux Standard Base) to check distribution details. The command relies on the lsb-release package, which you may need to install if it is not included by default. You can install it with sudo apt update && sudo apt install lsb-release. The first command refreshes the package list, and the second installs the package.

 

nwkt@Toni:~$ lsb_release -a

bash: lsb_release: command not found

 

nwkt@Toni:~$ sudo apt update && sudo apt install lsb-release

[sudo] password for nwkt:

<snipped for brevity>

 

nwkt@Toni:~$ lsb_release -a

No LSB modules are available.

Distributor ID: Debian

Description:    Debian GNU/Linux 13 (trixie)

Release:        13

Codename:       trixie

Example 1-8: Verify the Linux distribution (lsb_release).

Before installing Docker Engine, check the reserved memory and processor core count allocated to the WSL virtual machine. By default, Windows may allocate a large share of the available memory and many CPU cores to WSL. Examples 1-9 and 1-10 show how to verify the current allocation in WSL and in Windows PowerShell.

 

nwkt@Toni:~$  free –h && nproc

               total        used        free      shared  buff/cache   available

Mem:            62Gi       1.0Gi        61Gi       3.6Mi       180Mi        61Gi

Swap:           16Gi          0B        16Gi

36

Example 1-9: Check memory and CPU allocation (WSL).

 

PS C:\WINDOWS\system32> Get-Content "$env:USERPROFILE\.wslconfig"

[wsl2]

memory=61GB

processors=36

Example 1-10: Check memory and CPU allocation (PowerShell).

 

In this lab, the default WSL resource allocation exceeds the requirements, so you can reduce it. Example 1-11 shows how to shut down WSL and then update the .wslconfig file to set the memory and CPU limits.

 

 

PS C:\WINDOWS\system32> wsl --shutdown

PS C:\WINDOWS\system32> Set-Content -Path "$env:USERPROFILE\.wslconfig" -Value "[wsl2]`nmemory=32GB`nprocessors=8"

 

PS C:\WINDOWS\system32> Get-Content "$env:USERPROFILE\.wslconfig"

[wsl2]

memory=32GB

processors=8

Example 1-11: Adjust memory and CPU allocation.


 

Phase 4: Install Docker Engine



In this phase, install Docker Engine inside the Ubuntu distribution.

 

4.1 Install prerequisites

First, install the packages required to validate HTTPS certificates and download files from Docker’s repository.

 

nwkt@Toni:~$ sudo apt-get install ca-certificates curl gnupg lsb-release

Reading package lists... Done

Building dependency tree... Done

Reading state information... Done

ca-certificates is already the newest version (20240203).

curl is already the newest version (8.5.0-2ubuntu10.8).

gnupg is already the newest version (2.4.4-2ubuntu17.4).

lsb-release is already the newest version (12.0-2).

0 upgraded, 0 newly installed, 0 to remove and 2 not upgraded.

Example 1-12: Install prerequisites.

Next, create a directory for third-party repository keys. The sudo command is required because /etc is a protected system directory. The -p option creates the full directory path if it does not exist.

 

nwkt@Toni:~$ sudo mkdir -p /etc/apt/keyrings

Example 1-13: Create a keyring directory.

Ubuntu verifies a repository’s digital signature when downloading software using apt (Advanced Package Tool). To ensure that the Docker packages we install are authentic, we first download Docker’s GPG signing key and store it in the keyring directory created in the previous step. After that, every time packages are downloaded from the Docker repository, apt can verify that the packages come from Docker and have not been tampered with.

 

nwkt@Toni:~$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

Example 1-14: Add Docker’s GPG key.

 

4.2 Add the Docker repository

 

Before downloading the installation packages, add the official Docker repository to Ubuntu’s package source list. To ensure that the system downloads an authentic Docker version directly from Docker’s servers, we use the command shown below. Instead of manually typing platform-specific values, the command uses command substitution (the parts inside $( ... )) to detect the system architecture and the Ubuntu release codename.

The output displayed in the terminal is the result of the variables being "expanded" (replaced with actual values) before the text is written to the configuration file:

 

·         [arch=amd64]: Matches $(dpkg --print-architecture). It identifies that the system is running on a 64-bit Intel or AMD processor.

·         signed-by=/etc/apt/keyrings/docker.gpg: This path tells Ubuntu to use the specific GPG security key we downloaded earlier to verify that the Docker files haven't been tampered with.

·         https://download.docker.com/linux/ubuntu: This is the official URL of the Docker repository.

·         noble: Matches $(. /etc/os-release && echo "$VERSION_CODENAME"). It automatically identified that you are using Ubuntu 24.04, which is codenamed "noble" (see example 1-7: line VERSION_CODENAME=noble ).

·         stable: This indicates that we want the officially tested and stable version of Docker, rather than experimental or test builds.

 

nwkt@Toni:~$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list

#the command returns

deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu noble stable

Example 1-15: Add the Docker repository.

After adding the repository, run sudo apt-get update to synchronize the local package index with the Docker repository. This downloads the latest package lists so the Docker packages can be installed.

 

nwkt@Toni:~$ sudo apt-get update

Hit:1 http://security.ubuntu.com/ubuntu noble-security InRelease

Hit:2 http://archive.ubuntu.com/ubuntu noble InRelease

Get:3 https://download.docker.com/linux/ubuntu noble InRelease [48.5 kB]

Hit:4 http://archive.ubuntu.com/ubuntu noble-updates InRelease

Hit:5 http://archive.ubuntu.com/ubuntu noble-backports InRelease

Get:6 https://download.docker.com/linux/ubuntu noble/stable amd64 Packages [51.4 kB]

Fetched 99.9 kB in 1s (69.9 kB/s)

Reading package lists... Done

Example 1-16: Update the package index.


4.3 Install and start Docker Engine from the repository

Once the package index has been synchronized (Example 1-16), install Docker Engine and related components with sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin. This installs the Docker Engine (docker-ce), the Docker CLI (docker-ce-cli), and supporting components such as containerd.io and the Docker Compose plugin. After this step, your WSL Linux environment is ready to run containerized workloads such as a SONiC virtual switch.

 

nwkt@Toni:~$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

Reading package lists... Done

Building dependency tree... Done

Reading state information... Done

The following packages were automatically installed and are no longer required:

  bridge-utils dns-root-data dnsmasq-base ubuntu-fan

Use 'sudo apt autoremove' to remove them.

The following additional packages will be installed:

  docker-buildx-plugin docker-ce-rootless-extras libslirp0 slirp4netns

Suggested packages:

  cgroupfs-mount | cgroup-lite docker-model-plugin

The following packages will be REMOVED:

  containerd docker.io runc

The following NEW packages will be installed:

  containerd.io docker-buildx-plugin docker-ce docker-ce-cli docker-ce-rootless-extras docker-compose-plugin libslirp0 slirp4netns

0 upgraded, 8 newly installed, 3 to remove and 2 not upgraded.

Need to get 94.9 MB of archives.

After this operation, 87.5 MB of additional disk space will be used.

 

Do you want to continue? [Y/n] Y

Get:1 https://download.docker.com/linux/ubuntu noble/stable amd64 containerd.io amd64 2.2.3-1~ubuntu.24.04~noble [23.6 MB]

Get:2 http://archive.ubuntu.com/ubuntu noble/main amd64 libslirp0 amd64 4.7.0-1ubuntu3 [63.8 kB]

Get:3 http://archive.ubuntu.com/ubuntu noble/universe amd64 slirp4netns amd64 1.2.1-1build2 [34.9 kB]

Get:4 https://download.docker.com/linux/ubuntu noble/stable amd64 docker-ce-cli amd64 5:29.4.1-1~ubuntu.24.04~noble [17.0 MB]

Get:5 https://download.docker.com/linux/ubuntu noble/stable amd64 docker-ce amd64 5:29.4.1-1~ubuntu.24.04~noble [22.7 MB]

Get:6 https://download.docker.com/linux/ubuntu noble/stable amd64 docker-buildx-plugin amd64 0.33.0-1~ubuntu.24.04~noble [16.9 MB]

Get:7 https://download.docker.com/linux/ubuntu noble/stable amd64 docker-ce-rootless-extras amd64 5:29.4.1-1~ubuntu.24.04~noble [6559 kB]

Get:8 https://download.docker.com/linux/ubuntu noble/stable amd64 docker-compose-plugin amd64 5.1.3-1~ubuntu.24.04~noble [8023 kB]

Fetched 94.9 MB in 4s (26.4 MB/s)

(Reading database ... 41782 files and directories currently installed.)

Removing docker.io (29.1.3-0ubuntu3~24.04.1) ...

'/usr/share/docker.io/contrib/nuke-graph-directory.sh' -> '/var/lib/docker/nuke-graph-directory.sh'

Stopping 'docker.service', but its triggering units are still active:

docker.socket

Removing containerd (2.2.1-0ubuntu1~24.04.2) ...

Removing runc (1.3.4-0ubuntu1~24.04.1) ...

Selecting previously unselected package containerd.io.

(Reading database ... 41502 files and directories currently installed.)

Preparing to unpack .../0-containerd.io_2.2.3-1~ubuntu.24.04~noble_amd64.deb ...

Unpacking containerd.io (2.2.3-1~ubuntu.24.04~noble) ...

Selecting previously unselected package docker-ce-cli.

Preparing to unpack .../1-docker-ce-cli_5%3a29.4.1-1~ubuntu.24.04~noble_amd64.deb ...

Unpacking docker-ce-cli (5:29.4.1-1~ubuntu.24.04~noble) ...

Selecting previously unselected package docker-ce.

Preparing to unpack .../2-docker-ce_5%3a29.4.1-1~ubuntu.24.04~noble_amd64.deb ...

Unpacking docker-ce (5:29.4.1-1~ubuntu.24.04~noble) ...

Selecting previously unselected package docker-buildx-plugin.

Preparing to unpack .../3-docker-buildx-plugin_0.33.0-1~ubuntu.24.04~noble_amd64.deb ...

Unpacking docker-buildx-plugin (0.33.0-1~ubuntu.24.04~noble) ...

Selecting previously unselected package docker-ce-rootless-extras.

Preparing to unpack .../4-docker-ce-rootless-extras_5%3a29.4.1-1~ubuntu.24.04~noble_amd64.deb ...

Unpacking docker-ce-rootless-extras (5:29.4.1-1~ubuntu.24.04~noble) ...

Selecting previously unselected package docker-compose-plugin.

Preparing to unpack .../5-docker-compose-plugin_5.1.3-1~ubuntu.24.04~noble_amd64.deb ...

Unpacking docker-compose-plugin (5.1.3-1~ubuntu.24.04~noble) ...

Selecting previously unselected package libslirp0:amd64.

Preparing to unpack .../6-libslirp0_4.7.0-1ubuntu3_amd64.deb ...

Unpacking libslirp0:amd64 (4.7.0-1ubuntu3) ...

Selecting previously unselected package slirp4netns.

Preparing to unpack .../7-slirp4netns_1.2.1-1build2_amd64.deb ...

Unpacking slirp4netns (1.2.1-1build2) ...

Setting up docker-buildx-plugin (0.33.0-1~ubuntu.24.04~noble) ...

Setting up containerd.io (2.2.3-1~ubuntu.24.04~noble) ...

Setting up docker-compose-plugin (5.1.3-1~ubuntu.24.04~noble) ...

Setting up docker-ce-cli (5:29.4.1-1~ubuntu.24.04~noble) ...

Setting up libslirp0:amd64 (4.7.0-1ubuntu3) ...

Setting up docker-ce-rootless-extras (5:29.4.1-1~ubuntu.24.04~noble) ...

Setting up slirp4netns (1.2.1-1build2) ...

Setting up docker-ce (5:29.4.1-1~ubuntu.24.04~noble) ...

Could not execute systemctl:  at /usr/bin/deb-systemd-invoke line 148.

Processing triggers for man-db (2.12.0-4build2) ...

Processing triggers for libc-bin (2.39-0ubuntu8.7) ...

nwkt@Toni:~$

Example 1-17: Install Docker Engine.

The installation log shows that the package manager first identified and removed the default Ubuntu versions of Docker and its runtime components, specifically docker.io, containerd, and runc, to prevent conflicts with the official Docker versions. Once the old versions were removed, the system downloaded approximately 95 MB of archives from the official Docker repository and installed eight new packages, including the core Docker Engine (docker-ce), the command-line interface (docker-ce-cli), and the Docker Compose plugin. Additionally, essential networking libraries like libslirp0 and slirp4netns were installed to provide the necessary infrastructure for container networking in a virtualized environment.

During the process, we may see a notice about systemctl. This can occur in WSL environments where systemd is not enabled. In that case, services do not start via systemctl and must be started using alternative mechanisms (for example, the service command shown next).

Before downloading the SONiC image, we complete a few post-installation steps. First, we start the Docker service with sudo service docker start.

 

nwkt@Toni:~$ sudo service docker start

[sudo] password for nwkt:

nwkt@Toni:~$

Example 1-18: Start Docker Engine.

Next, we add our user to the Docker group with sudo usermod -aG docker $USER, then we restart the WSL session to apply the change.

nwkt@Toni:~$ sudo usermod -aG docker $USER

Example 1-19: Add your user to the docker group.

 

4.4 Install pv (optional)

It is also recommended to install the pv (Pipe Viewer) utility, which provides a progress bar when loading large compressed images into Docker.


nwkt@Toni:~$ sudo apt update && sudo apt install -y pv

Hit:1 http://security.ubuntu.com/ubuntu noble-security InRelease

Hit:2 https://download.docker.com/linux/ubuntu noble InRelease

Hit:3 http://archive.ubuntu.com/ubuntu noble InRelease

Hit:4 http://archive.ubuntu.com/ubuntu noble-updates InRelease

Hit:5 http://archive.ubuntu.com/ubuntu noble-backports InRelease

Reading package lists... Done

Building dependency tree... Done

Reading state information... Done

2 packages can be upgraded. Run 'apt list --upgradable' to see them.

Reading package lists... Done

Building dependency tree... Done

Reading state information... Done

The following packages were automatically installed and are no longer required:

  bridge-utils dns-root-data dnsmasq-base ubuntu-fan

Use 'sudo apt autoremove' to remove them.

Suggested packages:

  doc-base

The following NEW packages will be installed:

  pv

0 upgraded, 1 newly installed, 0 to remove and 2 not upgraded.

Need to get 73.9 kB of archives.

After this operation, 188 kB of additional disk space will be used.

Get:1 http://archive.ubuntu.com/ubuntu noble/main amd64 pv amd64 1.8.5-2build1 [73.9 kB]

Fetched 73.9 kB in 1s (87.4 kB/s)

Selecting previously unselected package pv.

(Reading database ... 41743 files and directories currently installed.)

Preparing to unpack .../pv_1.8.5-2build1_amd64.deb ...

Unpacking pv (1.8.5-2build1) ...

Setting up pv (1.8.5-2build1) ...

Processing triggers for man-db (2.12.0-4build2) ...

Example 1-20: Install pv (Pipe Viewer) (optional).

We verify the installation by running the docker run hello-world test container.

nwkt@Toni:~$ docker run hello-world

Unable to find image 'hello-world:latest' locally

latest: Pulling from library/hello-world

4f55086f7dd0: Pull complete

d5e71e642bf5: Download complete

Digest: sha256:f9078146db2e05e794366b1bfe584a14ea6317f44027d10ef7dad65279026885

Status: Downloaded newer image for hello-world:latest

 

Hello from Docker!

This message shows that your installation appears to be working correctly.

 

To generate this message, Docker took the following steps:

 1. The Docker client contacted the Docker daemon.

 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.

    (amd64)

 3. The Docker daemon created a new container from that image which runs the

    executable that produces the output you are currently reading.

 4. The Docker daemon streamed that output to the Docker client, which sent it

    to your terminal.

 

To try something more ambitious, you can run an Ubuntu container with:

 $ docker run -it ubuntu bash

 

Share images, automate workflows, and more with a free Docker ID:

 https://hub.docker.com/

 

For more examples and ideas, visit:

 https://docs.docker.com/get-started/

 

Example 1-21: Test Docker with Hello-world.

Finally, we confirm that we have enough free disk space for the SONiC image and the lab files.

nwkt@Toni:~$ df -h

Filesystem      Size  Used Avail Use% Mounted on

none             16G     0   16G   0% /usr/lib/modules/6.6.87.2-microsoft-standard-WSL2

none             16G  4.0K   16G   1% /mnt/wsl

drivers         953G  139G  815G  15% /usr/lib/wsl/drivers

/dev/sdd       1007G  5.8G  950G   1% /

none             16G   84K   16G   1% /mnt/wslg

none             16G     0   16G   0% /usr/lib/wsl/lib

rootfs           16G  2.7M   16G   1% /init

none             16G 1004K   16G   1% /run

none             16G     0   16G   0% /run/lock

none             16G     0   16G   0% /run/shm

none             16G   76K   16G   1% /mnt/wslg/versions.txt

none             16G   76K   16G   1% /mnt/wslg/doc

C:\             953G  139G  815G  15% /mnt/c

snapfuse         64M   64M     0 100% /snap/core20/2769

snapfuse        381M  381M     0 100% /snap/code/235

snapfuse         50M   50M     0 100% /snap/snapd/26865

tmpfs           3.2G   20K  3.2G   1% /run/user/1000

Example 1-22: Verify free disk space.

Phase 5: Install Containerlab


The last step before setting up a SONiC NOS-based network is to install Containerlab. Containerlab is an open-source orchestrator designed specifically for running network operating systems in a containerized environment. It simplifies SONiC deployments by automating the creation of virtual links and management interfaces defined in a YAML topology file. In this lab environment, Containerlab is already installed, so Example 1-23 is informational and does not show the full installation process.

 

nwkt@Toni:~$ bash -c "$(curl -sL https://get.containerlab.dev)"

nwkt@Toni:~$ which containerlab

/usr/bin/containerlab

nwkt@Toni:~$ cd /etc/containerlab

nwkt@Toni:/etc/containerlab$

 

Example 1-23: Install Containerlab.

Phase 6: Install the docker-sonic-vs.gz image

6.1 Download the docker-sonic-vs.gz image

 

The SONiC image used in this chapter is downloaded from:

https://sonic-build.azurewebsites.net/ui/sonic/pipelines

In this lab, I use the virtual switch platform (vs) from row 79 with BranchName 202411. Click Build History in the Builds column to open the list of builds.

 

 

 Home / Pipelines


 

SONiC Image Azure Pipelines

Go to All Azure Pipelines: here

Seq.

Platform

BranchName

DefinitionId

DefinitionName

Builds

1

aspeed-arm64

master

3372

Azure.sonic-buildimage.official.aspeed-arm64

Build History

79

vs

202411

142

Azure.sonic-buildimage.official.vs

Build History

 

Select a build where the Result column shows succeeded. In this book, build ID 1097472 is used. Then click the Artifacts link.

 

 

 Home / Pipelines / Builds

 

 

BuildId

BuildNumber

BranchName

BuildName

Result

StartTime

FinishTime

Commit

BuildLink

Artifacts

1099584

20260427.4

202411

Azure.sonic-buildimage.official.vs

failed

2026-04-27T08:00:48

2026-04-27T16:34:31

f1b9ef048d

Build Link

Artifacts

1098952

20260426.4

202411

Azure.sonic-buildimage.official.vs

succeeded

2026-04-26T08:06:51

2026-04-26T15:47:55

f1b9ef048d

Build Link

Artifacts

1098349

20260425.4

202411

Azure.sonic-buildimage.official.vs

succeeded

2026-04-25T08:00:36

2026-04-25T15:43:32

f1b9ef048d

Build Link

Artifacts

1097472

20260424.4

202411

Azure.sonic-buildimage.official.vs

succeeded

2026-04-24T08:06:46

2026-04-24T16:00:50

f1b9ef048d

Build Link

Artifacts

 

 

Select the sonic-buildimage.vs link in the Name column to open the artifact download page.

 

 

 Home / Pipelines / Builds / Artifacts

 

 

Seq.

ArtifactId

Name

1

1219546

sonic-buildimage.vs

 

 

In the file list, locate target/docker-sonic-vs.gz and select it to start the download.

 

 

 Home / Pipelines / Builds / Artifacts / Files

 

 

Seq.

Name

Size

Type

Latest Link

1

target

26002540805

directory

Copy Latest Static Link

2

target/_manifest

3169545

directory

Copy Latest Static Link

918

target/docker-sonic-vs.gz

225721287

file

Copy Latest Static Link

 

6.2 Copy the image to WSL

 

After downloading the image to Windows, create a folder structure ~/simple-lab/images for the lab environment. Then copy the downloaded docker-sonic-vs.gz file into WSL (for example, from /mnt/c/Users/<your-user>/Downloads) and verify that the file is present in the destination directory.

  

nwkt@Toni:/mnt/c/WINDOWS/system32$ cd ~

nwkt@Toni:~$

nwkt@Toni:~$ mkdir –p simple-lab/images && cd “$_”

nwkt@Toni:~/simple-lab/images$

nwkt@Toni:~/simple-lab/images$ cp /mnt/c/Users/NWKT/Downloads/docker-sonic-vs.gz .

nwkt@Toni:~/simple-lab/images$ ls

docker-sonic-vs.gz

Example 1-24: Create the project folders and copy the SONiC image.


6.3 Load the image into Docker

 

Next, load the docker-sonic-vs.gz image into Docker:

 

nwkt@Toni:~/simple-lab/images$ docker load < docker-sonic-vs.gz

6ade88c30b77: Loading layer [==============================================>]  121.4MB/121.4MB

2f468ee5a0d0: Loading layer [==============================================>]  138.2MB/138.2MB

4c1e1c77f38c: Loading layer [==============================================>]  1.536kB/1.536kB

a922292be2a7: Loading layer [==============================================>]  63.44MB/63.44MB

fc971f5af0da: Loading layer [==============================================>]  1.536kB/1.536kB

e7d7b92125c7: Loading layer [==============================================>]  29.25MB/29.25MB

ccdb24368e35: Loading layer [==============================================>]  1.536kB/1.536kB

c20dcc5a486a: Loading layer [==============================================>]  484.3MB/484.3MB

ff7d44d583aa: Loading layer [==============================================>]  1.536kB/1.536kB

The image docker-sonic-vs:latest already exists, renaming the old one with ID sha256:60ef70161146df78bd20a780d5ff3a38058e16d5b042f40d857a1c78d1b85974 to empty string

Loaded image: docker-sonic-vs:latest

nwkt@Toni:~/simple-lab/images$

Example 1-25: Load the docker-sonic-vs.gz image into Docker.

Phase 7:  Install Visual Studio Code on Windows



While we can use WSL’s built-in editor (such as nano) to create and edit YAML files, I am using Microsoft Visual Studio Code (VS Code). YAML relies on precise indentation, and VS Code makes this easier by providing visual indentation guides. You can download VS Code from various sources, including the Microsoft Store. During installation, enable the Add to PATH option so you can launch VS Code from within WSL.




 Figure 1-1: Visual Studio Code installation.

After installing VS Code, we connect it to our Linux environment. In VS Code, we select the Extensions icon (1) on the left sidebar, search for “WSL” (2), and then install the extension. The VS Code – WSL integration is done, and you can start VS Code from the WSL console using the code . command.


Figure 1-2: Visual Studio Code WSL extension.

The next chapter explains how to create a network topology file that defines a simple two-tier Clos topology with two SONiC leaf switches connected to a single spine switch.