При активном использовании подсистемы Windows Subsystem for Linux (WSL2) для запуска в Windows дистрибутивов Linux или контейнеров через Docker Desktop пользователи могут заметить, что размер виртуальных дисков ext4.vhdx постоянно растет. Вплоть до полного исчерпанная свободного места на системном диске хостовой Windows системы. По умолчанию в WSL2 используются динамические VHDX-файлы, размер которых увеличивается по мере записи в них новых данных, но файлы виртуальных дисков не сжимаются автоматически после удалении данных внутри них. В этой статье мы рассмотрим, как корректно уменьшить размер виртуальных дисков WSL (включая Docker Desktop) в Windows за счет их сжатия и оптимизации использования дискового пространства.
Как сжать файл виртуального VHDX диска WSL в Windows?
Итак, после неожиданного исчерпания места на системном диске в Windows, с помощью утилиты WinDirStat я обнаружил большой файл виртуального диска ext4.vhdx в профиле пользователя. Размер этого VHDX файл виртуальной машины WSL достигал почти 55 Гб (при начальном размере чистого WSL2 дистрибутива Ubuntu около 3 Гб).

Проверим фактически используемый (реальный) размер файлов в дистрибутиве WSL, выполнив в терминале команду:
df -h /

Определим точное местоположения VHDX файла вашего дистрибутива Linux в WSL. В Windows может быть установлено несколько дистрибутивов Linux WSL. Выведем их список командой:
wsl.exe --list --verbose
Скопируйте имя дистрибутива Linux (Ubuntu-24.04 в моем примере) и извлеките информацию о виртуальных дисках этого дистрибутива из реестра:
$distro='Ubuntu-24.04'
$vhdx=(Get-ChildItem -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss | Where-Object { $_.GetValue("DistributionName") -eq $distro}).GetValue("BasePath") + "\ext4.vhdx"
%USERPROFILE%\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu24.04LTS_79rhkp1fndgsc\LocalState\ext4.vhdx
Получим с помощью PowerShell фактический размер VHDX файла на диске:
"{0:N2} GB" -f ((Get-Item $VHDX).Length / 1GB)

Как вы видите, файл виртуального диска VHDX занимает несколько десятков Гб, хотя фактически используемый размер внутри дистрибутива Linux всего 3 Гб. Очевидно, что пользователь удалил файлы внутри WSL дистрибутива, но используемое место не высвободилось и требуется сжать VHDX диск.
$ sudo apt-get install ncdu
$ sudo ncdu --exclude /mnt

Найдите и удалите ненужные файлы, образы, логи и прочий мусор.
Можно удалить неиспользуемые пакеты и кеш (Ubuntu/Debian):
$ sudo apt-get update && sudo apt-get autoremove -y && sudo apt-get clean
Чтобы сжать виртуальный VHDX диск WSL, нужно остановить запущенный образ:
wsl --shutdown
Проверяем, что все образы остановлены:
wsl.exe --list -v

Для сжатия VHDX диска можно использовать PowerShell командлет Optimize-VHD. Чтобы сжать VHDX файл, выполните:
Optimize-VHD -Path C:\Users\sysops\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu24.04LTS_79rhkp1fndgsc\LocalState\ext4.vhdx -Mode full
Если этот командлет отсутствует, сжать виртуальный VHDX диск можно с помощью утилиты diskpart:
diskpart
Укажите путь к VHDX диску:
select vdisk file="C:\Users\sysops\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu24.04LTS_79rhkp1fndgsc\LocalState\ext4.vhdx"
Смонтируйте VHDX файл в режиме только на чтение:
attach vdisk readonly
Выполните сжатие:
compact vdisk
Отключите диск:
detach vdisk
exit

Проверьте, что после сжатия VHDX файла его реальный размер на диске существенно уменьшился до фактического размер данных, хранящихся в WSL.
Уменьшаем размер виртуального диска Docker Desktop в WSL
Если у вас на компьютере установлен Docker Desktop для Windows, он также использует WSL2 для запуска и хранит данные в виртуальном жестком диске формата VHDX. Такой VHDX файл постоянно растет по мере добавления образов, контейнеров и томов, но не уменьшается автоматически после их удаления.
Вывести фактически используемое место в Docker Desktop:
docker system df
Свободное место в VHDX файле Docker Desktop также можно сжать с помощью командлета Optimize-VHD или утилиты diskpart. Но сначала нужно удалить неиспользуемые образы и контейнеры Docker для очистки диск со стороны гостевой WSL:
docker system prune -a
По умолчанию данные Docker WSL хранятся в файле
%LOCALAPPDATA%\Docker\wsl\disk\ docker_data.vhdx
.
Закройте Docker Desktop и остановите подсистему WSL:
wsl --shutdown
После этого можете сжать файл docker_data.vhdx как описано выше. Например:
Optimize-VHD -Path "$env:LOCALAPPDATA\Docker\wsl\disk\docker_data.vhdx" -Mode Full
Включить разреженный (sparse) режима для VHDX диска в WSL 2
В WSL2 доступна экспериментальная опция для автоматического возврата неиспользуемого дискового пространства в VHDX файле хост системе. Sparse VHDX (разреженный виртуальный диск) основан на возможностях файловой системы NTFS и виртуализации Hyper-V, которые обеспечивают поддержку операций TRIM/UNMAP для файлов VHDX (есть риски повышенной фрагментации файлов при использовании на HDD). По сути, sparce реализует автоматическое сжатия виртуального VHDX диска WSL на лету.
Включить режим sparse для автоматического уменьшения размера VHDX для определенного дистрибутива WSL можно командой:
wsl --manage Ubuntu-24.04 --set-sparse true
При запуске появится предупреждение:
Sparse VHD support is currently disabled due to potential data corruption. To force a distribution to use a sparse VHD, please run: wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe Error code: Wsl/Service/E_INVALIDARG

Чтобы игнорировать предупреждение и включить экспериментальный режим sparse принудительно, выполните:
wsl --manage Ubuntu-24.04 --set-sparse true --allow-unsafe
Также можно включить sparse в конфигурационном файле %UserProfile%\.wslconfig:
[experimental] sparseVhd=true
После включения этой опции VHDX файл автоматически сжимает после удаления данных внутри него без остановки виртуальной машины WSL.
Перед тем как включать режим sparse, оптимизируйте размер VHDX файла с помощью diskpart или Optimize-VHD, т.к. после включения опции вы не сможете выполнить сжатие файла этими командами.

