A PowerShell script for automated Docker maintenance on Windows with WSL2 backend. This script performs monthly Docker cleanup and virtual disk compaction to prevent disk space bloat and maintain optimal Docker performance.
Docker Desktop with WSL2 backend can accumulate significant disk space over time due to:
- Unused containers, images, and build cache
- WSL2 virtual disk files that grow but never shrink automatically
- Dangling volumes and networks
This script automates the cleanup process and can reclaim substantial disk space (users typically see 20-140GB+ freed during initial runs).
- ✅ Automated Docker cleanup - Removes unused containers, images, networks, and build cache
- ✅ WSL2 virtual disk compaction - Shrinks Docker's virtual disk file to actual usage size
- ✅ Graceful Docker daemon shutdown - Prevents "WSL distro terminated abruptly" errors
- ✅ Comprehensive logging - Detailed logs for monitoring and troubleshooting
- ✅ Safe restart sequence - Ensures Docker Desktop restarts cleanly after maintenance
- ✅ Multiple fallback methods - Handles different Docker Desktop versions and configurations
- ✅ Production ready - Designed for unattended monthly automation
- Windows 10/11 with WSL2 enabled
- Docker Desktop with WSL2 backend
- PowerShell 5.1 or later
- Administrator privileges (required for diskpart operations)
- Download the script to your preferred location (e.g., C:\Scripts)
- Create the log directory: New-Item -ItemType Directory -Path "C:\Logs" -Force
- Test the script by running it manually first
.\docker_wsl_compact_vdisk.ps1
.\docker_wsl_compact_vdisk.ps1 -LogPath "D:\MyLogs\DockerCleanup.log"
- Open Task Scheduler as Administrator
- Create Basic Task → Name: "Docker Monthly Cleanup"
- Trigger: Monthly (first Sunday at 3:00 AM recommended)
- Action: Start a program
- Program: powershell.exe
- Arguments: -ExecutionPolicy Bypass -File "C:\Scripts\docker_wsl_compact_vdisk.ps1"
- Settings:
- ✅ Check "Run with highest privileges" (REQUIRED)
- ✅ Check "Run whether user is logged on or not"
- Configure for: Windows 10/11
$trigger = New-JobTrigger -Weekly -WeeksInterval 4 -DaysOfWeek Sunday -At 3AM
Register-ScheduledJob -Name "DockerMonthlyCleanup" -ScriptBlock { & "$env:USERPROFILE\dev\docker_wsl_compact_vdisk\docker_wsl_compact_vdisk.ps1" } -Trigger $trigger
- Removes all unused containers
- Removes all unused images (including dangling images)
- Removes all unused networks
- Clears Docker build cache
- Reports space reclaimed
- Stops Docker daemon using docker desktop stop
- Terminates Docker WSL distros if needed
- Safely shuts down WSL subsystem
- Locates Docker's WSL virtual disk (docker_data.vhdx)
- Uses Windows diskpart to compact the virtual disk
- Reports actual disk space reclaimed
- Kills any lingering Docker processes
- Restarts Docker Desktop using
docker desktop startCLI (preferred) - Falls back to launching Docker Desktop.exe if CLI unavailable
- Waits for Docker daemon to be ready (up to 3 minutes)
- Verifies successful startup
- Docker cleanup: 5-50GB typically freed
- Disk compaction: 20-140GB+ reclaimed from bloated virtual disk
- Total time: 2-5 minutes
- Docker cleanup: 2-20GB freed (depends on usage)
- Disk compaction: 1-10GB reclaimed
- Total time: 1-3 minutes
Logs are stored at C:\Logs\DockerCleanup.log by default and include:
- Timestamp for each operation
- Docker disk usage before/after cleanup
- Space reclaimed by each phase
- Any errors or warnings
- Complete diskpart output for troubleshooting
2025-09-16 01:26:39 - === Starting Docker Monthly Cleanup === 2025-09-16 01:26:44 - Initial usage: Images: 8.069GB, Containers: 64.88MB, Volumes: 25.76GB 2025-09-16 01:26:45 - Gracefully stopping Docker daemon... 2025-09-16 01:27:11 - Docker daemon stopped successfully via CLI 2025-09-16 01:27:17 - Initial VHDX size: 40.22 GB 2025-09-16 01:27:45 - Final VHDX size: 40.22 GB 2025-09-16 01:27:52 - Docker is ready. Version: 27.4.0 2025-09-16 01:27:52 - === Docker Monthly Cleanup Completed Successfully ===
- Cause: Scheduled task not running with highest privileges
- Solution: Edit scheduled task → Check "Run with highest privileges"
- Note: The
docker desktop startCLI command requires admin rights to work from scheduled tasks
- Symptoms: Script completes but Docker doesn't start automatically
- Manual fix:
- Open Task Manager → End all Docker processes
- Launch Docker Desktop from Start menu
- Prevention: Ensure scheduled task has "Run with highest privileges" checked
- Cause: Script not running as Administrator
- Solution: Always run PowerShell as Administrator or enable "Run with highest privileges" in Task Scheduler
- Cause: Non-standard Docker installation location
- Solution: Check script logs for actual disk location and update path
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
The script automatically detects Docker's WSL disk in these locations:
- %LOCALAPPDATA%\Docker\wsl\disk\docker_data.vhdx (primary)
- %LOCALAPPDATA%\Docker\wsl\data\ext4.vhdx (fallback)
- Docker Desktop 4.0+ with WSL2 backend
- Works with both Windows Home and Pro editions
- Administrator check - Prevents permission issues
- Docker readiness verification - Ensures Docker is operational before cleanup
- Multiple shutdown methods - Graceful → Forceful fallback
- Error handling - Comprehensive try/catch blocks
- Process verification - Confirms each step before proceeding
This script is provided as-is for personal and commercial use. No warranty implied.
Disk space is precious. Keep your Docker installation clean! 🐳✨