All That Dev

Setting up Docker in Windows 11 using WSL2

September 19, 2024 | by Cícero Fabio

allthaedev.com.backgroud

In this guide, I’ll walk you through my experience of setting up a development environment on Windows using containerized applications without Docker Desktop. While Docker Desktop is convenient, it’s no longer free, so I explored a cost-effective alternative using WSL2 (Windows Subsystem for Linux) and Ubuntu.

This process is streamlined to help you get Docker running on your machine quickly. If you’re familiar with Docker, Linux, PowerShell, and bash, you’re good to go!


Objective

We’ll set up a container runtime environment using WSL2, Ubuntu, and dockerd, enabling you to run containers from both Linux and Windows without Docker Desktop.


Prerequisites

  1. Enable WSL2 & Virtualization Features on Windows

Run the following commands in PowerShell to enable the necessary features:

Enable-WindowsOptionalFeature -Online -FeatureName 'Containers' -All
Enable-WindowsOptionalFeature -Online -FeatureName 'Microsoft-Hyper-V' -All
Enable-WindowsOptionalFeature -Online -FeatureName 'VirtualMachinePlatform' -All
Enable-WindowsOptionalFeature -Online -FeatureName 'Microsoft-Windows-Subsystem-Linux' -All
  1. Install Windows Terminal

Install the Windows Terminal from the Microsoft Store for a better console experience.

  1. Install Microsoft PowerShell

Install the latest version of PowerShell using the Windows package manager:

winget install --id 'Microsoft.Powershell' --scope machine
  1. Install Ubuntu (WSL)

Install the Ubuntu distribution via winget:

winget install Ubuntu

Once installed, set up your Linux user account.


Setting up Docker in WSL2 (Ubuntu)

  1. Update and Upgrade Packages

Open the Ubuntu terminal and update your packages:

sudo apt update && sudo apt upgrade
  1. Install Docker Prerequisites
sudo apt install --no-install-recommends apt-transport-https ca-certificates curl gnupg2
  1. Add Docker Repository
source /etc/os-release
curl -fsSL https://download.docker.com/linux/${ID}/gpg | sudo apt-key add -
echo "deb [arch=amd64] https://download.docker.com/linux/${ID} ${VERSION_CODENAME} stable" | sudo tee /etc/apt/sources.list.d/docker.list
  1. Install Docker
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io
  1. Add User to Docker Group
sudo usermod -aG docker $USER
  1. Configure Docker Daemon

Create a daemon.json configuration file for Docker:

sudo mkdir /etc/docker/
sudo vi /etc/docker/daemon.json

Add the following contents:

{
  "hosts": ["tcp://0.0.0.0:2375"],
  "tls": false
}
  1. Launch Docker Daemon
sudo dockerd &

To stop the daemon, use:

sudo pkill dockerd

Verifying Docker Setup

  1. Check that Docker is working:
docker -H 127.0.0.1 run --rm hello-world

If successful, export the Docker host for future commands:

export DOCKER_HOST="tcp://127.0.0.1:2375"

Building Docker CLI for Windows

  1. Clone the Docker CLI repository:
git clone https://github.com/docker/cli.git
cd cli
  1. Build Docker CLI for Windows:
docker buildx bake
docker buildx bake --set binary.platform=windows/amd64
  1. Copy the docker-windows-amd64.exe to your Windows tools directory (e.g., C:\tools):
cp build/docker-windows-amd64.exe /mnt/c/tools
  1. Rename it to docker.exe:
cd c:\tools
ren docker-windows-amd64.exe docker.exe

Using Docker CLI on Windows

  1. Find the IP of your WSL host using PowerShell:
wsl -- ip -o -4 -json addr list eth0 | ConvertFrom-Json | %{ $_.addr_info.local } | ?{ $_ }
  1. Run a Docker command with your WSL IP:
docker -H <YOUR_WSL_IP> ps
  1. Optionally, create a Docker context for WSL:
docker context create wsl --docker "host=tcp://<YOUR_WSL_IP>:2375"
docker context use wsl

Automating IP Updates

WSL may change its IP address after each reboot, so create a PowerShell script to update the Docker context automatically:

$wslip = wsl -- ip -o -4 -json addr list eth0 | ConvertFrom-Json | ForEach-Object { $_.addr_info.local } | Where-Object { $_ }
$ctx = docker context ls --format json | ConvertFrom-Json | Where-Object { $_.Name -eq "wsl" }
if($null -eq $ctx) {
    Write-Host "Creating Docker context 'wsl' to host=tcp://$($wslip):2375"
    docker context create wsl --docker "host=tcp://$($wslip):2375" | Out-Null
} else {
    docker context update wsl --docker "host=tcp://$($wslip):2375" | Out-Null
}
docker context use wsl | Out-Null

Now, your Docker environment is ready to go, without needing a Docker Desktop!


This clean and streamlined setup allows you to use Docker on Windows 11 with WSL2 and Ubuntu, all without the need for Docker Desktop!