I currently maintain two development environments: one Linux and one Windows 11.
On Linux, this kind of problem is much less frequent for me. On Windows 11, however, Docker Desktop + WSL2 occasionally ends up in a strange state: Docker gets stuck on Loading, docker-desktop shows up as Installing, the daemon doesn't respond, or WSL is left with stuck processes/services.
After going through this a few times, I ended up keeping a saved PowerShell script to perform a more aggressive reset of the environment.
The idea is simple: restart what needs to be restarted without wiping my WSL distributions or my development environment.
The script
Run PowerShell as Administrator.
#requires -RunAsAdministrator
$ErrorActionPreference = "SilentlyContinue"
Write-Host "=== Docker Desktop + WSL2 - Hard reset ===" -ForegroundColor Cyan
Write-Host ""
#
# Terminates the WSL client to release processes that may be stuck.
taskkill.exe /F /IM "wsl.exe" 2>$null
# Terminates the WSL distribution hosts that may remain stuck.
taskkill.exe /F /IM "wslhost.exe" 2>$null
# Terminates the in-process WSL service in case it is stuck during shutdown.
taskkill.exe /F /IM "wslservice.exe" 2>$null
# Terminates the VMM process used by the WSL2 distributions' backend.
taskkill.exe /F /IM "VmmemWSL.exe" 2>$null
# Completely closes the Docker Desktop interface.
taskkill.exe /F /IM "Docker Desktop.exe" 2>$null
# Terminates the main Docker Desktop backend.
taskkill.exe /F /IM "com.docker.backend.exe" 2>$null
# Terminates the HNS process when it gets stuck in STOP_PENDING or START_PENDING.
taskkill.exe /F /IM "svchost.exe" /FI "SERVICES eq hns"
Write-Host ""
Write-Host "[1/8] Stopping services..." -ForegroundColor Yellow
# Tries to stop the modern WSL service if available in this installation.
Stop-Service WSLService -Force -ErrorAction SilentlyContinue
# Tries to stop the legacy service if it exists in older WSL versions.
Stop-Service LxssManager -Force -ErrorAction SilentlyContinue
# Stops the compute service used by virtual machines and WSL2.
Stop-Service vmcompute -Force -ErrorAction SilentlyContinue
# Stops the Host Network Service used by WSL2 and Docker networking.
Stop-Service hns -Force -ErrorAction SilentlyContinue
Write-Host "[2/8] Checking HNS..." -ForegroundColor Yellow
# Displays the detailed HNS state to identify stuck processes.
sc.exe queryex hns
Write-Host ""
Write-Host "[3/8] Checking VM Compute..." -ForegroundColor Yellow
# Displays the detailed state of the virtual machine compute service.
sc.exe queryex vmcompute
Write-Host ""
Write-Host "[4/8] Starting services again..." -ForegroundColor Yellow
# Starts the compute service required by the WSL2 backend.
Start-Service vmcompute -ErrorAction SilentlyContinue
# Starts the Host Network Service used by the Docker and WSL2 virtual network.
Start-Service hns -ErrorAction SilentlyContinue
# Starts the modern WSL service when available in this version.
Start-Service WSLService -ErrorAction SilentlyContinue
Write-Host ""
Write-Host "[5/8] Service status..." -ForegroundColor Yellow
# Shows only the WSL, HNS and VM Compute services available on this machine.
Get-Service WSLService,LxssManager,hns,vmcompute -ErrorAction SilentlyContinue |
Format-Table Status,Name,DisplayName -AutoSize
Write-Host ""
Write-Host "[6/8] WSL status..." -ForegroundColor Yellow
# Lists all distributions and confirms whether the Docker backend is registered.
wsl.exe -l -v
# Displays the current configuration of the WSL2 installed on the machine.
wsl.exe --status
Write-Host ""
Write-Host "[7/8] Starting Docker Desktop..." -ForegroundColor Yellow
# Starts the Docker Desktop service before opening its interface.
Start-Service com.docker.service -ErrorAction SilentlyContinue
# Opens Docker Desktop to reinitialize the Linux backend.
$dockerDesktop = "$env:ProgramFiles\Docker\Docker\Docker Desktop.exe"
if (Test-Path $dockerDesktop) {
Start-Process $dockerDesktop
}
else {
Write-Warning "Docker Desktop.exe not found at: $dockerDesktop"
}
Write-Host ""
Write-Host "[8/8] Waiting for the Docker backend..." -ForegroundColor Yellow
# Waits for Docker Desktop to start its distribution and its internal daemon.
Start-Sleep -Seconds 15
# Shows the state of the WSL distributions again after startup.
wsl.exe -l -v
Write-Host ""
Write-Host "=== Docker validation ===" -ForegroundColor Cyan
# Tests whether the Docker client can connect to the Linux daemon.
docker.exe version
# Shows daemon information to confirm the backend is operational.
docker.exe info
# Displays the Docker contexts and highlights the currently selected one.
docker.exe context ls
Write-Host ""
Write-Host "=== Reset complete ===" -ForegroundColor Green
What does it do?
Basically, the script tries to clear stuck WSL2, Docker Desktop and HNS processes, restarts the necessary services, and then validates the state of WSL and Docker.
The most important point, in my view, is that it does not remove my Ubuntu distributions and does not start by deleting containers, volumes or images.
A real example
In one of the cases I ran into, the environment was inconsistent.
WSL showed something like:
NAME STATE VERSION
Ubuntu-22.04 Stopped 2
docker-desktop Installing 2
Ubuntu Stopped 2
While Docker returned a connection error with:
dockerDesktopLinuxEngine
And an attempt to directly access:
wsl.exe -d docker-desktop
returned:
Wsl/Service/WSL_E_DISTRO_NOT_FOUND
I've also found HNS stuck in states such as:
START_PENDING
or:
STOP_PENDING
In these cases, simply running wsl --shutdown or restarting Docker Desktop was not enough.
An important detail
The script is a recovery routine, not a guarantee that Docker Desktop will start automatically.
For example, in one run Windows managed to leave:
hns Running
vmcompute Running
WSLService Running
and WSL went back to showing:
docker-desktop Stopped 2
but the Docker Desktop executable was not at the path the script expected.
In that scenario, the script still did its part in recovering WSL/services, but Docker Desktop had to be started manually.
This is also useful because it shows that "healthy WSL" and "healthy Docker daemon" are different things.
⚠️ Be careful with wsl --unregister
There is a second procedure that I keep separate from the main script:
wsl.exe --unregister docker-desktop
This command is not a restart.
wsl --unregister removes the specified WSL distribution. Therefore, it can remove data stored in that distribution and, depending on how Docker Desktop is configured, affect Docker's internal state.
For that reason, I do not put this command in the normal script flow.
I only use it in a specific situation where:
docker-desktop Installing
but:
wsl.exe -d docker-desktop
returns:
Wsl/Service/WSL_E_DISTRO_NOT_FOUND
Even in that case, it should be treated as a last resort.
And a personal rule in my environment:
DO NOT run:
wsl --unregister Ubuntu
wsl --unregister Ubuntu-22.04
These are my development distributions and are not part of the normal Docker recovery process.
My summary
For me, this script has become a kind of "hard reset" for Docker Desktop + WSL2 on Windows 11.
It is not an official Docker or Microsoft procedure. It is simply a personal recovery playbook based on the problems I've run into in my development environment.
Having the script saved is much more practical than manually repeating the same sequence every time Docker Desktop decides to get stuck on Loading.
Top comments (0)