Skip to the content.

Native Docker in WSL - even in a VM, No Docker Desktop

docker

Install WSL in a VM

We need to Enable Nested VM (Powershel on the parent host machine)

Set-VMProcessor -VMName "_FayedVM" -ExposeVirtualizationExtensions $true

How to locate the .vhdx file and disk path for your Linux distribution

(Get-ChildItem -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss | Where-Object { $_.GetValue("DistributionName") -eq '<DistributionName>' }).GetValue("BasePath") + "\ext4.vhdx"

# The result will display a path looking something like %LOCALAPPDATA%\Packages\<PackageFamilyName>\LocalState\<disk>.vhdx. For example:
# C:\Users\fayed\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu_79rhkp1fndgsc\LocalState\ext4.vhdx

How to expand the size of your WSL 2 Virtual Hard Disk: https://learn.microsoft.com/en-us/windows/wsl/disk-space


Steps to install Docker in WSL

Longin as root, to avoid using sudo many times

sudo -i
apt update && apt upgrade

if you faced DNS connectrviy issue:

echo -e "[network]\ngenerateResolvConf = false" | tee -a /etc/wsl.conf
unlink /etc/resolv.conf
echo nameserver 1.1.1.1 | tee /etc/resolv.conf

remove old versions:

apt remove docker docker-engine docker.io containerd runc

Install dependencies

apt install --no-install-recommends apt-transport-https ca-certificates curl gnupg2 -y

switch to legacy iptables

update-alternatives --config iptables
# And select [ iptables-legacy ]

Ubuntu package repository configuration

cat /etc/os-release

# note the ID (ubuntu in my case) and VERSION_CODENAME (jammy in my case) and use them in the bellow lines:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | tee /etc/apt/trusted.gpg.d/docker.asc
echo "deb [arch=amd64] https://download.docker.com/linux/ubuntu jammy stable" | tee /etc/apt/sources.list.d/docker.list
apt update

Install Docker

apt install docker-ce docker-ce-cli containerd.io -y

update docker-compose to latest version ( https://github.com/docker/compose/releases/)

curl -L "https://github.com/docker/compose/releases/download/v2.22.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

chmod +x /usr/local/bin/docker-compose
docker-compose --version

Create non-root-user, create home directory, and set default shell to bash (you can change it later with chsh command):

useradd -m -s /bin/bash [UserName]

set password and add the user to sudo and docker groups:

passwd [UserName]
usermod -aG sudo [UserName]
usermod -aG docker [UserName]

Passwordless launch of dockerd:

su [UserName]
echo "`whoami` ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/`whoami` && sudo chmod 0440 /etc/sudoers.d/`whoami`

Test

docker run --rm hello-world

Auto Start Docker:

echo 'sudo service docker start' >> ~/.profile
	
# OR:

echo '# Start Docker daemon automatically when logging in if not running.' >> ~/.bashrc
echo 'RUNNING=`ps aux | grep dockerd | grep -v grep`' >> ~/.bashrc
echo 'if [ -z "$RUNNING" ]; then' >> ~/.bashrc
echo '    sudo dockerd > /dev/null 2>&1 &' >> ~/.bashrc
echo '    disown' >> ~/.bashrc
echo 'fi' >> ~/.bashrc

change the WSL default login user, replace USER_NAME with the desired user name:

echo -e "[user]\ndefault=USER_NAME" >> /etc/wsl.conf

Call WSL executable from Windows

if you named this file dig.bat it will call the dig command from Linux in your WSL

@echo off
SETLOCAL EnableExtensions
SETLOCAL DisableDelayedExpansion
set v_params=%*
set v_params=%v_params:\=/%
set v_params=%v_params:c:=/mnt/c%
set DOCKER_DISTRO=Ubuntu
C:\Windows\system32\wsl.exe -d %DOCKER_DISTRO% %~n0 %v_params%

Calling Docker from Windows PowerShell ;)

Open your PowerShell profile:

notepad $profile

# %USERPROFILE%\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

Then Add the following:

$DOCKER_DISTRO = "Ubuntu"
function docker {
    wsl -d $DOCKER_DISTRO docker @Args
}
function docker-compose {
    wsl -d $DOCKER_DISTRO docker-compose @Args
}

Calling Docker from Windows Command Prompt

create 2 batch files docker.bat, docker-compose.bat and add them to any location included in your %PATH%

for docker.bat, add the following:

@echo off
set DOCKER_DISTRO=Ubuntu
wsl -d %DOCKER_DISTRO% docker %*

for docker-compose.bat, add the following:

@echo off
set DOCKER_DISTRO=Ubuntu
wsl -d %DOCKER_DISTRO% docker-compose %*

VSCode Docker extention

Although the above solutions works well from Windows PowerShell and Commmand Prombet, they don’t work the VS Code Docker Extenstion but there is a solution ;)

Downmload these shims for both Dokcer and Docker-Compose and add them to your path https://github.com/trakos/docker-wsl-shim

VSCode DevContainer

the solution that worked for me is to open my code folder from WSL, then open in DevContainer (better to have your code in a native Linux path like /code/.. rather than a mounted Windows path like /mnt/c/...)


sources: