Reclaiming Disk Space from Docker's WSL 2 VHDX File

Reclaiming Disk Space from Docker's WSL 2 VHDX File

A practical guide to understanding why Docker Desktop's virtual disk balloons on Windows — and how to shrink it back down.


Background: WSL 2 and Why Docker Relies on It

WSL 2 (Windows Subsystem for Linux 2) is Microsoft's lightweight virtualization technology that runs a real Linux kernel directly on Windows, without the overhead of a traditional virtual machine. Docker Desktop adopted it as the default backend because it delivers tangible benefits:

  • Full Linux syscall compatibility — containers behave exactly as they would on native Linux.
  • Faster file I/O — particularly for workloads inside the Linux filesystem.
  • Seamless container isolation — all running on your C: drive without partitioning.

The trade-off is the VHDX file: a single virtual disk that stores the entire Linux distribution's state. Without periodic maintenance, it grows quickly and never gives space back on its own.

Why the VHDX File Grows Uncontrollably

Docker stores its Linux filesystem in ext4.vhdx, typically located at:

%LOCALAPPDATA%\Docker\wsl\disk\docker_data.vhdx

This file is dynamically expanding — it gets larger as you pull images, run containers, and accumulate build caches. But here's the catch: it never shrinks automatically when you delete those resources. Unused image layers, dangling volumes, and orphaned data linger inside the virtual disk until you both prune them in Docker and compact the VHDX itself. The result is often gigabytes of trapped space.


Step 1: Prune Docker Junk

Make sure Docker Desktop is running (check the system tray), then open PowerShell as Administrator.

Start with a sweeping cleanup that removes unused resources in one shot:

docker system prune -a --volumes

This command removes dangling images, stopped containers, unused networks, and unreferenced volumes. If you need finer control, run the targeted commands individually:

docker image prune -a
docker container prune
docker volume prune

Confirm the cleanup worked by checking disk usage from Docker's perspective:

docker system df

You should see space reclaimed immediately — but only inside the VHDX. The file on disk hasn't shrunk yet.

Step 2: Optimize the VHDX to Shrink It

Pruning alone doesn't reduce the VHDX file size on Windows. You need to compact it manually.

Update WSL First

For best results, make sure you're on WSL 2.5 or newer, which has improved VHDX compaction:

wsl --update
wsl --version

You should see version 2.5.10 or higher. Restart Docker Desktop after updating.

Compact the Disk

In the same Administrator PowerShell window:

  1. Shut down WSL so the VHDX is no longer in use:
    wsl --shutdown
    
  2. Locate the VHDX file. The default path is %LOCALAPPDATA%\Docker\wsl\disk\docker_data.vhdx. A tool like TreeSize can help confirm the location and current size.
  3. Run the compact operation:
    Optimize-VHD -Path "$env:LOCALAPPDATA\Docker\wsl\disk\docker_data.vhdx" -Mode Full
    

Optimize-VHD scans the virtual disk and reclaims unused blocks, returning that space to your Windows drive. Verify the result with TreeSize or by checking the file's properties.

Note: Optimize-VHD is part of the Hyper-V module. If the cmdlet isn't recognized, enable the Hyper-V Management Tools feature via "Turn Windows features on or off."


Pro Tip: Cap WSL's Disk Size Going Forward

To prevent the VHDX from ever ballooning past a sensible limit, create or edit %USERPROFILE%\.wslconfig with the following:

[wsl2]
memory=8GB       # Caps WSL VM RAM at 8GB (default: 50% of system RAM)
swap=0           # Disables swap to avoid extra VHDX growth
diskSize=100GB   # Max VHDX size (default: 1TB) — choose wisely

A few things worth knowing:

  • The diskSize value is a hard cap. Once set, the VHDX cannot grow beyond it, so pick a number that comfortably fits your largest expected workload.
  • Changes only take effect after wsl --shutdown followed by restarting Docker Desktop.
  • If you set a value smaller than the current VHDX size, you may need to expand it manually later — there's no easy way to shrink the cap below an already-grown disk.

Quick Reference

GoalCommand
Remove unused Docker resourcesdocker system prune -a --volumes
Check Docker disk usagedocker system df
Update WSLwsl --update
Shut down WSLwsl --shutdown
Compact the VHDXOptimize-VHD -Path "<path>" -Mode Full

Run this maintenance routine every few weeks if you build images frequently — your C: drive will thank you.