Skip to content

mtgroupsrls/Shrink-DockerDataVHDX

Repository files navigation

Shrink-DockerDataVHDX

Compact Docker Desktop's VHDX safely on Windows with PowerShell automation.

Reclaim disk space by compacting Docker Desktop's docker_data.vhdx safely through zero-filling free space inside the Docker WSL distro and then running a host-side compaction. This script does not install any distro — it uses Docker Desktop's built-in docker-desktop WSL distro.

PowerShell License: MIT


Table of Contents


What it does

  1. Validates the environment (WSL installed, Docker distro exists, VHDX accessible) and checks host drive free space
  2. Analyzes potential space savings before running (estimates reclaimable GB)
  3. Optionally simulates the plan (-WhatIf) or prompts for confirmation (unless -Force)
  4. Zero-fills free space inside the Docker data disk using incremental cycles (write N GB at a time) or a single full zero-fill
  5. Shuts down WSL so the VHDX is not in use
  6. Compacts the VHDX using Optimize-VHD (Hyper-V module) if available, otherwise falls back to diskpart compact vdisk
  7. Displays comprehensive progress with real-time updates, elapsed time tracking, and final summary statistics

Requirements

  • Windows with PowerShell 5.1 or later
  • Docker Desktop with WSL2 backend (includes the docker-desktop distro by default)
  • Sufficient host free disk space for temporary VHDX growth during zero-filling
    • Incremental mode available to limit peak space usage
  • Optional: Hyper-V PowerShell module for Optimize-VHD (recommended but not required — diskpart is used as fallback)

Admin privileges: The script automatically elevates itself when needed (except in -WhatIf simulation mode)


Installation

  1. Download or save the script as Shrink-DockerDataVHDX.ps1

  2. No need to "Run as Administrator" — the script will automatically elevate itself when needed

  3. If your execution policy prevents running scripts, use:

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

Or run with bypass:

powershell -ExecutionPolicy Bypass -File .\Shrink-DockerDataVHDX.ps1

Note: When the script needs admin privileges, Windows will show a UAC prompt asking for permission to elevate.


Usage

.\Shrink-DockerDataVHDX.ps1 [-Mode <Interactive|Incremental|Full|Auto>] [-MinFreeSpaceGB <int>]
                            [-VhdxRelativePath <string>] [-Force] [-WhatIf]
                            [-MaxIncrementalSizeGB <int>] [-MaxCycles <int>]

Parameters

Parameter Type Default Description
-Mode string Interactive Operation mode: Interactive (Menu), Incremental, Full, or Auto.
-MinFreeSpaceGB int 20 Minimum free space (GB) required on host drive before proceeding
-VhdxRelativePath string Docker\wsl\disk\docker_data.vhdx Path relative to %LOCALAPPDATA%
-Force switch - Skip interactive prompts (confirmation & elevation). Fails if not Admin.
-WhatIf switch - Simulation mode — show plan without making changes (no admin required)
-MaxIncrementalSizeGB int 0 If > 0, write N GB per cycle and compact between cycles
-MaxCycles int 10 Maximum cycles to run in incremental mode

Examples

1. Dry run (simulation) — No admin required

.\Shrink-DockerDataVHDX.ps1 -WhatIf

Output example:

[WhatIf] Plan summary:
  VHDX: C:\Users\YourName\AppData\Local\Docker\wsl\disk\docker_data.vhdx
  Host drive free: 45.23 GB
  MinFreeSpaceGB: 20
  Full-mode: write filler until disk full inside docker-desktop, then shutdown and compact
  Force: no
[SIMULATION] Starting simulated execution...
[SIM] Cycle 1 of 1 - Writing 25 GB (full mode)...
[SIM] ✓ Compaction complete (simulated)
========================================
         COMPACTION COMPLETE (SIMULATED)
========================================
Initial VHDX size:  85.3 GB
Final VHDX size:    85.3 GB (simulated)
Space saved:        0 GB (0%) - simulation only
========================================
This is a simulation only; no actions were executed.

2. Full (single-shot) run with confirmation

.\Shrink-DockerDataVHDX.ps1

The script will analyze system conditions, show the recommended mode, then display a menu:

[Auto-Select] Analyzing system conditions...
  Free space: 45 GB
  Minimum required: 20 GB
  VHDX size: 60 GB
[Auto-Select] → FULL MODE (Plenty of disk space - faster approach)

Choose an option:
1) Simulate Full mode
2) Simulate Incremental mode
3) Run Full mode (danger zone - requires admin)
4) Run Incremental mode (safer - requires admin)
5) Exit

Type 'YES' to proceed, anything else to abort:

3. Force non-interactive full run

.\Shrink-DockerDataVHDX.ps1 -Mode Full -Force

4. Incremental mode — 10 GB per cycle, up to 5 cycles

.\Shrink-DockerDataVHDX.ps1 -Mode Incremental -MaxIncrementalSizeGB 10 -MaxCycles 5 -Force

Best for: Systems with limited free space or when you want more control over the process.

5. Auto mode - Let the script choose the best mode

.\Shrink-DockerDataVHDX.ps1 -Mode Auto -WhatIf

Auto mode intelligently selects:

  • Full mode when you have plenty of disk space (> 2x MinFreeSpaceGB and > 50 GB free)
  • Incremental mode when disk space is limited or VHDX is very large

Output example:

[Auto-Select] Analyzing system conditions...
  Free space: 7 GB
  Minimum required: 20 GB
  VHDX size: 60 GB

[Auto-Select] → **INCREMENTAL MODE** (Limited disk space - safer approach)
  Reason: Free space ratio (0.35) indicates tight disk space

6. Custom VHDX location with lower safety threshold

.\Shrink-DockerDataVHDX.ps1 -VhdxRelativePath "CustomPath\docker.vhdx" -MinFreeSpaceGB 10

How incremental mode works

Incremental mode helps avoid large temporary spikes in host disk usage. Each cycle:

  1. Measures host free space and ensures at least MinFreeSpaceGB remains
  2. Writes a zero-filled file of N GB inside /mnt/docker-desktop-disk/zero.fill (in docker-desktop distro)
  3. Syncs and removes the filler file
  4. Shuts down WSL with wsl --shutdown
  5. Compacts the VHDX using Optimize-VHD or diskpart
  6. Re-measures host free space and repeats until MaxCycles reached or insufficient headroom

Progress tracking: Each cycle displays elapsed time, space saved, and overall progress (e.g., "Cycle 3 (max 5)"). Note: Shows "(max N)" because actual cycles may be fewer based on available disk space.

┌─────────────────────────────────────────────────────────────�
│ Cycle 1: Write 10GB → Compact → Reclaim space              │
│ Cycle 2: Write 10GB → Compact → Reclaim space              │
│ Cycle 3: Write 10GB → Compact → Reclaim space              │
│ ...                                                          │
└─────────────────────────────────────────────────────────────┘

Progress Indicators

The script provides comprehensive progress feedback:

  • PowerShell progress bars showing current operation and elapsed time
  • Real-time VHDX size monitoring during compaction (when using Optimize-VHD)
  • Per-cycle statistics in incremental mode (space saved, time taken)
  • Periodic console updates so you know the script is still working
  • Final summary report showing:
    • Initial vs final VHDX size
    • Total space saved (GB and percentage)
    • Operation completion time

Example output:

========================================
         COMPACTION COMPLETE
========================================
Initial VHDX size:  85.3 GB
Final VHDX size:    52.1 GB
Space saved:        33.2 GB (38.9%)
========================================

Safety & Notes

  • ⚠️ Interruption risks: DO NOT KILL the script during VHDX compaction (Optimize-VHD or diskpart operations). Killing during this phase can corrupt the VHDX and make Docker unusable. Zero-fill phase is safer to interrupt if absolutely necessary.

  • 🐳 Docker Desktop Protection: The script actively monitors for Docker Desktop:

    • Pre-execution: Blocks if Docker Desktop is running (requires exclusive VHDX access)
    • During compaction: Monitors every 3-5 seconds for Docker starting
    • Critical protection: Immediately stops compaction if Docker starts to prevent corruption
    • Auto-close: Can force-close Docker Desktop (interactive mode waits for manual close)
  • 🔐 Self-elevation: Script automatically requests admin privileges when needed via UAC prompt

  • 💾 Host disk space: Zero-filling temporarily expands the VHDX. Ensure sufficient free space or use incremental mode

  • 🔒 Backup first: Always backup important data before manipulating VHDX files

  • âš¡ Optimize-VHD vs diskpart: Optimize-VHD (Hyper-V module) is faster and preferred; diskpart is used as automatic fallback

  • ðŸ�§ Minimal environment: The docker-desktop distro is minimal — the script only writes to /mnt/docker-desktop-disk, no package installation needed

  • ðŸ"Š Space monitoring: Script checks host free space and aborts if below -MinFreeSpaceGB

  • ðŸ›' Docker Desktop impact: Docker Desktop will be stopped during the process (WSL shutdown required for compaction)

  • ðŸ🤖 Auto-configuration: When free space is limited (< 10 GB), the script automatically adjusts parameters for safety:

    • Reduces MinFreeSpaceGB to 3-5 GB
    • Reduces MaxIncrementalSizeGB to 2 GB
    • Warns about tight disk space conditions

Troubleshooting

"VHDX not found"

Cause: Docker Desktop not installed or VHDX at non-default location
Solution: Verify Docker Desktop installation. Check VHDX location at %LOCALAPPDATA%\Docker\wsl\disk\docker_data.vhdx or specify custom path with -VhdxRelativePath

"This script must be run as Administrator"

Cause: Self-elevation failed or was cancelled
Solution:

  • If you cancelled the UAC prompt, run the script again and approve the elevation request
  • Alternatively, manually run PowerShell as Administrator before running the script
  • Note: -WhatIf simulation mode doesn't require admin privileges

Optimize-VHD not available

Status: Not an error — the script automatically uses diskpart fallback
To enable Optimize-VHD: Install Hyper-V PowerShell module:

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-Management-PowerShell

DiskPart errors

Cause: Process locking the VHDX (WSL still running or Docker Desktop active)
Solution: Ensure WSL is stopped. The script calls wsl --shutdown automatically, but verify with:

wsl --list --running

Host drive fills during run

Cause: Insufficient free space for full zero-fill operation
Solution:

  • Stop script immediately (Ctrl+C)
  • Use smaller -MaxIncrementalSizeGB value (e.g., 5 or 10 GB)
  • Increase -MinFreeSpaceGB threshold for more safety margin
  • Move VHDX to larger drive (requires Docker Desktop reconfiguration)

Script hangs during zero-fill

Cause: Normal behavior — zero-filling large amounts of space takes time
Expected duration: Can take 15-60+ minutes depending on disk size and speed
Monitor: The script shows progress bars and periodic status updates. If you see the progress bar and elapsed time updating, the script is working correctly.


FAQ

Q: Do I need to run PowerShell as Administrator?
A: No! The script automatically elevates itself when needed. Just double-click or run normally, and approve the UAC prompt when it appears.

Q: How much space can I reclaim?
A: Depends on how much unused space is in your Docker containers/images. Typical savings: 10-50% of current VHDX size.

Q: Will this delete my Docker images/containers?
A: No, this only compacts free space. Your Docker data remains intact.

Q: How long does it take?
A: Typically 15-60 minutes depending on VHDX size and disk speed. Incremental mode is slower but safer.

Q: Can I run this on a schedule?
A: Yes, use Windows Task Scheduler with the -Force parameter for automated runs. Configure the task to run with highest privileges.

Q: Does this work with Docker Desktop using Hyper-V backend?
A: This script is designed for WSL2 backend. Hyper-V backend uses different VHDX locations.


Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.


Development & Testing

This project includes automated checks to ensure code quality and safety.

Local Testing

  1. Static Analysis: Run the included helper script to check for syntax errors and best practices.
    .\Run-PSScriptAnalyzer.ps1
  2. Simulation: Always run with -WhatIf before committing changes.
    .\Shrink-DockerDataVHDX.ps1 -WhatIf
  3. Manual Checklist: Refer to TEST_CHECKLIST.md for a step-by-step guide to manually validating the script.

CI/CD

A GitHub Actions workflow (.github/workflows/ps1-test.yml) automatically runs on every push and pull request to ensure code quality and functionality:

Automated Checks:

  1. PSScriptAnalyzer Linting

    • Scans for Errors, Warnings, and Information level issues
    • Fails build on Error severity issues
    • Reports all findings for quality tracking
  2. Syntax Validation

    • Verifies PowerShell syntax is valid
    • Prevents broken scripts from being merged
  3. Functional Testing

    • Executes -WhatIf simulation to ensure script runs without crashing
    • Tests multiple parameter combinations:
      • Custom MinFreeSpaceGB values
      • Incremental mode with different cycle sizes
      • Force flag behavior
      • Auto mode with system analysis
  4. Code Quality Checks

    • Scans for TODO/FIXME/HACK comments
    • Reports technical debt for tracking

Triggers:

  • Push to main branch
  • Pull request against main branch
  • Manual trigger via GitHub Actions UI

Runner: windows-latest (Windows VM)

Changelog

See CHANGELOG.md for the full version history and release notes.

License

This project is licensed under the MIT License - see the LICENSE file for details.


Acknowledgments

  • Inspired by the need to manage Docker Desktop's disk usage on Windows
  • Uses standard Windows tools (WSL, diskpart, Optimize-VHD) for maximum compatibility

Made with �� for Docker Desktop users fighting disk space issues

About

Safely compact Docker Desktop's docker_data.vhdx on Windows using PowerShell, zero-filling free space inside the Docker WSL distro and running VHDX compaction.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors