Docker
WSL
ext4.vhdx
storage management
disk space

Docker Desktop WSL ext4.vhdx too large

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

The ext4.vhdx file is the virtual hard disk that WSL 2 uses to store the Linux filesystem for Docker Desktop. It grows automatically as you pull images and create containers, but it never shrinks on its own when you delete data. To reclaim space, you need to first clean up Docker resources with docker system prune, then compact the VHDX file using either Optimize-VHD (Hyper-V) or wsl --manage --resize (Windows 11+). Without the compaction step, the file stays at its peak size regardless of how much data you delete.

Why the File Grows But Never Shrinks

WSL 2 uses a dynamically expanding virtual hard disk in VHD format. The file starts small and grows as data is written to the Linux filesystem. However, the VHD format does not automatically reclaim space when files are deleted inside the virtual disk. The filesystem marks blocks as free internally, but the host NTFS filesystem still sees those blocks as allocated in the VHDX file.

This behavior means that a developer who pulls 50 GB of Docker images, deletes them all, and runs docker system prune will still have a 50 GB ext4.vhdx file on disk.

Where to Find the File

The default locations for the Docker Desktop VHDX file:

powershell
1# Docker Desktop WSL data
2%LOCALAPPDATA%\Docker\wsl\data\ext4.vhdx
3
4# Or under the distro directory
5%LOCALAPPDATA%\Docker\wsl\distro\ext4.vhdx
6
7# Check actual size
8Get-Item "$env:LOCALAPPDATA\Docker\wsl\data\ext4.vhdx" | Select-Object Length, @{N='SizeGB';E={[math]::Round($_.Length/1GB,2)}}

You may also find VHDX files for other WSL distributions at:

powershell
# Generic WSL distro location
%LOCALAPPDATA%\Packages\CanonicalGroupLimited.Ubuntu*\LocalState\ext4.vhdx

Step 1: Clean Up Docker Resources

Before compacting the virtual disk, remove everything Docker no longer needs. This frees space inside the virtual filesystem so the compaction step has something to reclaim.

bash
1# Remove all stopped containers, unused networks, dangling images, and build cache
2docker system prune -a --volumes
3
4# Check how much space Docker is using
5docker system df
6
7# More targeted cleanup if you want to keep some images
8docker container prune          # Remove stopped containers
9docker image prune -a           # Remove all unused images
10docker volume prune             # Remove unused volumes
11docker builder prune -a         # Remove all build cache
12docker network prune            # Remove unused networks

Understanding docker system df Output

bash
1$ docker system df
2TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
3Images          45        3         12.8GB    11.2GB (87%)
4Containers      12        2         1.5GB     1.3GB (86%)
5Local Volumes   8         2         4.2GB     3.8GB (90%)
6Build Cache     124       0         6.1GB     6.1GB (100%)

The "RECLAIMABLE" column shows how much space docker system prune can recover. In this example, pruning would free roughly 22 GB inside the virtual disk.

Step 2: Compact the VHDX File

After cleaning up Docker resources, the space is free inside the Linux filesystem but the VHDX file on the Windows host is still the same size. You need to compact it.

Method 1: Optimize-VHD (Requires Hyper-V)

This method works on Windows 10/11 Pro, Enterprise, or Education with Hyper-V enabled.

powershell
1# Step 1: Shut down WSL completely
2wsl --shutdown
3
4# Step 2: Compact the VHDX file (run PowerShell as Administrator)
5Optimize-VHD -Path "$env:LOCALAPPDATA\Docker\wsl\data\ext4.vhdx" -Mode Full
6
7# Step 3: Verify the new size
8Get-Item "$env:LOCALAPPDATA\Docker\wsl\data\ext4.vhdx" | Select-Object @{N='SizeGB';E={[math]::Round($_.Length/1GB,2)}}

Method 2: diskpart (Works on Windows Home)

For Windows Home editions that do not have Hyper-V:

powershell
1# Step 1: Shut down WSL
2wsl --shutdown
3
4# Step 2: Open diskpart
5diskpart
6
7# Step 3: Inside diskpart, run these commands
8select vdisk file="C:\Users\YourUsername\AppData\Local\Docker\wsl\data\ext4.vhdx"
9compact vdisk
10
11# Step 4: Exit diskpart
12exit

Method 3: wsl --manage (Windows 11 22H2+)

Recent Windows 11 builds support resizing directly through the WSL CLI:

powershell
1# Shut down WSL
2wsl --shutdown
3
4# Set a maximum size (e.g., 80 GB) - this caps future growth
5wsl --manage docker-desktop-data --set-sparse true
6
7# On builds that support it
8wsl --manage docker-desktop-data --resize 80GB

The --set-sparse flag is particularly useful because it enables automatic space reclamation on future deletes, solving the root cause rather than treating the symptom.

Preventing Future Growth

Set Docker Resource Limits

In Docker Desktop settings, you can limit the virtual disk size:

  1. Open Docker Desktop Settings
  2. Go to Resources then Advanced
  3. Set "Disk image max size" to a reasonable limit (e.g., 64 GB)

Use .wslconfig to Limit WSL Resources

ini
1# Create or edit %USERPROFILE%\.wslconfig
2[wsl2]
3memory=8GB
4processors=4
5swap=2GB

Implement Regular Cleanup

Create a scheduled cleanup script:

powershell
1# save as cleanup-docker.ps1
2Write-Host "Docker disk usage before cleanup:"
3docker system df
4
5docker system prune -a --volumes -f
6
7Write-Host "`nDocker disk usage after cleanup:"
8docker system df
9
10Write-Host "`nShutting down WSL for compaction..."
11wsl --shutdown
12Start-Sleep -Seconds 5
13
14Write-Host "Compacting VHDX..."
15Optimize-VHD -Path "$env:LOCALAPPDATA\Docker\wsl\data\ext4.vhdx" -Mode Full
16
17$size = (Get-Item "$env:LOCALAPPDATA\Docker\wsl\data\ext4.vhdx").Length / 1GB
18Write-Host "VHDX size after compaction: $([math]::Round($size, 2)) GB"

Use Multi-Stage Builds

Large images are often the primary cause of VHDX bloat. Multi-stage builds keep the final image small:

dockerfile
1# Build stage - large, includes compilers and build tools
2FROM node:20 AS builder
3WORKDIR /app
4COPY package*.json ./
5RUN npm ci
6COPY . .
7RUN npm run build
8
9# Production stage - small, only runtime dependencies
10FROM node:20-alpine
11WORKDIR /app
12COPY --from=builder /app/dist ./dist
13COPY --from=builder /app/node_modules ./node_modules
14CMD ["node", "dist/index.js"]

Comparison of Compaction Methods

MethodWindows EditionRequires AdminAutomatic ReclaimNotes
Optimize-VHDPro/Enterprise/EducationYesNoMost reliable, requires Hyper-V module
diskpart compactAll editions including HomeYesNoWorks everywhere, slightly slower
wsl --manage --set-sparse11 22H2+NoYesBest long-term fix, prevents regrowth
wsl --manage --resize11 22H2+NoNoSets a hard cap on disk size

Common Pitfalls

  • Running compaction without cleaning Docker first. If you compact the VHDX while Docker images are still present, you reclaim nothing. Always docker system prune -a --volumes before compacting.
  • Forgetting to shut down WSL before compacting. The VHDX file is locked while WSL is running. Optimize-VHD and diskpart will fail or produce corrupt results if WSL is still active. Always run wsl --shutdown first and wait a few seconds.
  • Using docker system prune without the -a flag. Without -a, Docker only removes dangling images (untagged intermediate layers). With -a, it removes all images not used by a running container. The difference can be tens of gigabytes.
  • Not realizing volumes survive docker system prune. You need the --volumes flag to prune named volumes. Without it, persistent data volumes remain and continue consuming space.
  • Trying Optimize-VHD on Windows Home. The Hyper-V PowerShell module is not available on Home editions. Use the diskpart method instead.
  • Compacting too infrequently. If you wait until the VHDX file consumes your entire disk, the compaction process itself may fail due to insufficient temporary space. Schedule monthly compaction.

Summary

The ext4.vhdx file grows as Docker stores images, containers, and volumes in the WSL 2 virtual disk, but it never shrinks automatically. Reclaiming space is a two-step process: first clean Docker resources with docker system prune -a --volumes, then compact the VHDX file using Optimize-VHD (Hyper-V), diskpart compact vdisk (Windows Home), or wsl --manage --set-sparse true (Windows 11 22H2+ for automatic future reclamation). For long-term prevention, limit Docker's disk image size in settings, use multi-stage builds to keep images small, and schedule regular cleanup scripts. The sparse file option in recent Windows 11 builds is the most effective solution because it addresses the root cause by enabling automatic space reclamation.


Course illustration
Course illustration

All Rights Reserved.