DEV Community

Miro
Miro

Posted on

1

WSL2 Containers

Because, why not?

Playing around with WSL2, I figured it could be used to make one-off build containers. In a similar way I usually use docker.

For example, building TDLib for Telegram Messenger.

My run.cmd is simple:

@echo off
wsl --import alpine-build .\VM alpine-minirootfs-3.12.0-x86_64.tar.gz
wsl -d alpine-build /bin/sh /mnt/e/Temp/TDLib/build.sh
wsl --unregister alpine-build
  1. Install alpine distribution by running wsl --import
  2. Execute the build script
  3. Unregister the distribution

Build script, build.sh , is made using TDLib Build instrunction generator, with the addition of the OUT_DIR variable just to make it easier.

OUT_DIR=/mnt/e/Temp/TDLib/lib

cd ~
apk update
apk upgrade
apk add --update alpine-sdk linux-headers git zlib-dev openssl-dev gperf php php-ctype cmake
git clone https://github.com/tdlib/td.git
cd td
git checkout v1.6.0
rm -rf build
mkdir build
cd build
export CXXFLAGS=""
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=$OUT_DIR ..
cmake --build . --target install
cd ..
cd ..
ls -l $OUT_DIR

Running it and it works.

PS E:\Temp\TDLib> .\run.cmd
fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/community/x86_64/APKINDEX.tar.gz
v3.12.0-214-g4076381e49 [http://dl-cdn.alpinelinux.org/alpine/v3.12/main]
v3.12.0-213-gfedcac4c0f [http://dl-cdn.alpinelinux.org/alpine/v3.12/community]
OK: 12749 distinct packages available
(1/6) Upgrading musl (1.1.24-r8 -> 1.1.24-r9)
<snip>
-- The CXX compiler identification is GNU 9.3.0
-- The C compiler identification is GNU 9.3.0
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ - works
<snip>
-- Configuring done
-- Generating done
-- Build files have been written to: /root/td/build
Scanning dependencies of target tdsqlite
[  0%] Building C object sqlite/CMakeFiles/tdsqlite.dir/sqlite/sqlite3.c.o
[  0%] Linking C static library libtdsqlite.a
[  0%] Built target tdsqlite
<snip>
Scanning dependencies of target bench_queue
[100%] Building CXX object benchmark/CMakeFiles/bench_queue.dir/bench_queue.cpp.o
[100%] Linking CXX executable bench_queue
[100%] Built target bench_queue
Install the project...
-- Install configuration: "Release"
-- Installing: /mnt/e/Temp/TDLib/lib/lib/libtdjson.so.1.6.0
-- Installing: /mnt/e/Temp/TDLib/lib/lib/libtdjson.so
-- Installing: /mnt/e/Temp/TDLib/lib/lib/libtdjson_static.a
-- Installing: /mnt/e/Temp/TDLib/lib/lib/libtdjson_private.a
<snip>
total 0
drwxrwxrwx    1 root     root           512 Aug  7 14:03 include
drwxrwxrwx    1 root     root           512 Aug  7 14:03 lib
Unregistering...
PS E:\Temp\TDLib>

Not as versatile as docker run but does the job.

Using differencing disks

Using differencing disks, I can have all build tools installed in the base vhdx and spawn "build container" just for a single build.

For example, based on above, I've created base

PS E:\Temp> wsl --import Alpine-BuildBase E:\WSL2\Alpine-BuildBase E:\WSL2\alpine-minirootfs-3.12.0-x86_64.tar.gz

And installed everything I need

apk update
apk upgrade
apk add --update alpine-sdk linux-headers git zlib-dev openssl-dev gperf php php-ctype cmake

Now my build.sh omits tools installation and looks like:

OUT_DIR=/mnt/e/Temp/TDLib/lib

cd ~
git clone https://github.com/tdlib/td.git
cd td
git checkout v1.6.0
rm -rf build
mkdir build
cd build
export CXXFLAGS=""
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=$OUT_DIR ..
cmake --build . --target install
cd ..
cd ..
ls -l $OUT_DIR

And the final part, run.ps1 PowerShell script that will:

  1. Create differencing vhdx
  2. Make a registry key for the linux distribution "container"
  3. Execute the build script
  4. Unregister the distribution
#Must be run as an Administrator
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
    Start-Process PowerShell -Verb RunAs "-NoProfile -ExecutionPolicy Bypass -Command `"cd '$pwd'; & '$PSCommandPath';`"";
    exit;
}

$DISTRO_NAME = "alpine-build"

#Create a new differencing VHD
New-Item -Path VM -ItemType Directory -Force | Out-Null
New-VHD -ParentPath E:\WSL2\Alpine-BuildBase\ext4.vhdx -Path .\VM\ext4.vhdx -Differencing -BlockSizeBytes 1048576

#Add a registry key
$guid = New-Guid
$RegKey = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss\" + $guid.ToString("B")
New-Item -Path $RegKey
New-ItemProperty -Path $RegKey -Name BasePath -PropertyType String -Value $PWD\VM | Out-Null
New-ItemProperty -Path $RegKey -Name DefaultUid -PropertyType DWord -Value 0 | Out-Null
New-ItemProperty -Path $RegKey -Name DistributionName -PropertyType String -Value $DISTRO_NAME | Out-Null
New-ItemProperty -Path $RegKey -Name Flags -PropertyType DWord -Value 15 | Out-Null
New-ItemProperty -Path $RegKey -Name State -PropertyType DWord -Value 1 | Out-Null
New-ItemProperty -Path $RegKey -Name Version -PropertyType DWord -Value 2 | Out-Null

#Run the build script
wsl -d $DISTRO_NAME /bin/sh /mnt/e/Temp/TDLib/build.sh

#Unregister the distribution
wsl --unregister $DISTRO_NAME

#Pause
Read-Host -Prompt "Press Enter key to continue"

Just testing

To make sure above script works as expected instead of running the build script (line 25 above) I can swap it with

wsl -d $DISTRO_NAME /bin/sh -c "date && cat /etc/*-release"

Result is

ComputerName            : PC123
Path                    : E:\Temp\TDLib\VM\ext4.vhdx
VhdFormat               : VHDX
VhdType                 : Differencing
FileSize                : 6291456
Size                    : 274877906944
MinimumSize             :
LogicalSectorSize       : 512
PhysicalSectorSize      : 4096
BlockSize               : 1048576
ParentPath              : E:\WSL2\Alpine-BuildBase\ext4.vhdx
DiskIdentifier          : A96ADE57-4838-48EA-97A9-DE02790ADCB4
FragmentationPercentage :
Alignment               : 1
Attached                : False
DiskNumber              :
IsPMEMCompatible        : False
AddressAbstractionType  : None
Number                  :

Property      : {}
PSPath        : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss\{4
                e9ced54-7d28-48d2-92de-1df93ddc55a9}
PSParentPath  : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss
PSChildName   : {4e9ced54-7d28-48d2-92de-1df93ddc55a9}
PSDrive       : HKCU
PSProvider    : Microsoft.PowerShell.Core\Registry
PSIsContainer : True
SubKeyCount   : 0
View          : Default
Handle        : Microsoft.Win32.SafeHandles.SafeRegistryHandle
ValueCount    : 0
Name          : HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss\{4e9ced54-7d28-48d2-92de-1df93ddc55a9}

Fri Aug  7 15:27:17 UTC 2020
3.12.0
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.12.0
PRETTY_NAME="Alpine Linux v3.12"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://bugs.alpinelinux.org/"
Unregistering...
Press Enter key to continue:

Conclusion

I'm not sure if this has a practical value. Maybe in scenarios where it is easier to have a single file virtual disk rather than a docker container stored in some registry. But it was an interesting concept to explore. Let me know if you find it useful.

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay