WSLのディスク容量を圧迫するvhdxファイルを圧縮・管理する方法【Windows 11】

WSLを日常的に使っていると、Cドライブの空き容量がじわじわ減っていくことに気づく。原因の大半は、WSLが内部で使っている仮想ディスクファイルの肥大化にある。この記事では、その仕組みと具体的な対処法を整理する。

目次

WSLのストレージが膨らむ仕組み

WSL2は、Linuxファイルシステムを vhdx(Virtual Hard Disk Extended) という形式の仮想ディスクファイルに格納している。vhdxはMicrosoftの仮想ハードディスクフォーマットで、Hyper-Vや仮想マシンでも使われる形式だ。

WSL2のディストリビューションごとに1つのvhdxファイルが作成され、デフォルトでは以下のようなパスに置かれる。

%USERPROFILE%\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu...\LocalState\ext4.vhdx

このvhdxファイルには厄介な特性がある。ファイルの追加に応じて自動的にサイズが拡張されるが、ファイルを削除しても自動的には縮小されないという点だ。たとえばDockerイメージを大量にpullして削除した場合、Linux側の使用量は減っていても、Windows側のvhdxファイルは膨らんだままになる。

以下の図は、この仕組みを示したものだ。

Windows 11 ファイルシステム(NTFS) ext4.vhdx(仮想ディスクファイル) 拡張はするが、自動では縮小しない Linux ファイルシステム(ext4) 実際のデータはここに格納 ファイル追加 → vhdx拡張 自動で大きくなる ファイル削除 → vhdx据え置き 自動では縮まない

つまり、WSLを長く使うほどvhdxファイルは一方的に大きくなる。これがCドライブ圧迫の正体だ。

現在のディスク使用量を確認する

対処の前に、まず現状を把握する。

Linux側の使用量を確認

WSLのターミナルで以下を実行する。

df -h /

Usedの列がLinux内で実際に使われている容量だ。

Windows側のvhdxファイルサイズを確認

PowerShellで以下を実行する。

Get-ChildItem -Path "$env:USERPROFILE\AppData\Local\Packages\*Ubuntu*\LocalState\ext4.vhdx" | Select-Object FullName, @{Name="SizeGB";Expression={[math]::Round($_.Length/1GB, 2)}}

Ubuntuの部分はディストリビューション名に合わせて変更する。Docker Desktopを使っている場合は、以下のパスも確認する。

Get-ChildItem -Path "$env:USERPROFILE\AppData\Local\Docker\wsl\data\ext4.vhdx" | Select-Object FullName, @{Name="SizeGB";Expression={[math]::Round($_.Length/1GB, 2)}}

Linux側の使用量とvhdxファイルサイズの差が大きいほど、圧縮で回収できる容量が多い。

vhdxファイルを圧縮する

本題の圧縮手順に入る。WSL2には、vhdxを最適化(未使用領域の解放)するための仕組みがいくつか用意されている。

wsl –manage による圧縮(推奨)

Windows 11のWSL 2.0.9以降では、--manageコマンドでvhdxを直接圧縮できる。最も手軽な方法だ。

まずWSLを停止する。

wsl --shutdown

次に圧縮を実行する。

wsl --manage <ディストリビューション名> --compact

ディストリビューション名はwsl -l -vで確認できる。たとえばUbuntuなら以下のようになる。

wsl --manage Ubuntu --compact

このコマンドがエラーになる場合は、WSLのバージョンが古い可能性がある。wsl --updateで最新版に更新してから再試行する。

Hyper-V(diskpart)による圧縮

--manageが使えない環境や、より細かく制御したい場合はdiskpartを使う方法がある。

まずWSLを停止する。

wsl --shutdown

PowerShellを管理者権限で起動し、diskpartを実行する。

diskpart

diskpartのプロンプトで以下を順に入力する。

select vdisk file="C:\Users\<ユーザー名>\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu...\LocalState\ext4.vhdx"
compact vdisk
exit

パスは実際のvhdxの場所に置き換える。compact vdiskの実行にはvhdxのサイズに応じて数分〜数十分かかることがある。

圧縮前にLinux側で不要データを削除する

圧縮の効果を最大化するために、事前にLinux側のゴミを掃除しておくとよい。

# パッケージキャッシュの削除
sudo apt clean

# 不要パッケージの削除
sudo apt autoremove -y

# ユーザーキャッシュの削除(中身を確認してから)
du -sh ~/.cache/*
rm -rf ~/.cache/pip ~/.cache/npm

# Dockerを使っている場合
docker system prune -a --volumes

特にDockerの未使用イメージやボリュームは数GB〜数十GBになっていることが珍しくない。docker system prune -a --volumesは使っていないコンテナ・イメージ・ボリュームをすべて削除するので、必要なものまで消えないか確認してから実行する。

vhdxの保存先をCドライブ以外に移動する

圧縮だけでは根本的に解決しないケースもある。開発で大量のデータを扱う場合、vhdxの保存先自体をDドライブなど別のドライブに移すのが有効だ。

手順は以下の通り。

WSLを停止する。

wsl --shutdown

ディストリビューションをtarファイルにエクスポートする。

wsl --export Ubuntu D:\wsl-backup\ubuntu.tar

既存のディストリビューションを登録解除する。

wsl --unregister Ubuntu

注意:--unregisterを実行すると元のvhdxは削除される。エクスポートが完了していることを必ず確認してから実行する。

別ドライブにインポートする。

wsl --import Ubuntu D:\wsl\Ubuntu D:\wsl-backup\ubuntu.tar

インポート後、デフォルトユーザーがrootになるため、元のユーザーに戻す設定が必要だ。/etc/wsl.confに以下を追記する。

[user]
default=<あなたのユーザー名>

その後WSLを再起動すれば、元のユーザーでログインできる。

移動前後のディスク配置の違いを示す。

移動前 移動後 Cドライブ(NTFS) OS + アプリ + ext4.vhdx ext4.vhdx(肥大化) Dドライブ(空き十分) Cドライブ(NTFS) OS + アプリのみ(軽量) Dドライブ(NTFS) ext4.vhdx(こちらに移動)

この方法ならCドライブの容量を気にせずWSLを運用できる。

スパースファイルの自動回収を有効にする

WSLの最近のバージョンでは、vhdxの未使用領域を自動的に回収する機能が追加されている。.wslconfigで設定することで、手動圧縮の頻度を減らせる。

%USERPROFILE%\.wslconfigに以下を追記する。

[wsl2]
sparseVhd=true

設定後、WSLを再起動する。

wsl --shutdown

sparseVhd=trueを設定すると、vhdxファイルがスパースファイル(実際に使用している領域だけディスクを消費するファイル形式)として扱われ、未使用領域が自動的に解放されるようになる。

ただし、この設定は新規作成されるvhdxに対して適用される点に注意が必要だ。既存のvhdxをスパース化するには、一度エクスポート→アンレジスター→インポートの手順を踏む必要がある。前述の移動手順と同じ要領で、インポート先を同じ場所にすればよい。

Docker Desktopのストレージ管理

WSLでDocker Desktopを使っている場合、Docker専用のvhdxが別途存在し、これが最大の容量消費源になっていることも多い。

Docker Desktopのvhdxは通常以下にある。

%USERPROFILE%\AppData\Local\Docker\wsl\data\ext4.vhdx

Docker側のストレージ節約には以下が有効だ。

対策コマンド効果
未使用リソースの一括削除docker system prune -a --volumes停止コンテナ・未使用イメージ・ボリュームを削除
ビルドキャッシュの削除docker builder prune -aビルド時のキャッシュレイヤーを削除
使用状況の確認docker system df -vイメージ・コンテナ・ボリュームごとの容量を表示

pruneでLinux側のデータを削除した後、前述のwsl --managediskpartでDocker用のvhdxも圧縮すると、大幅に容量を回収できる。Docker Desktopのディストリビューション名はdocker-desktop-dataであることが多い。

wsl --manage docker-desktop-data --compact

定期的なメンテナンスの仕組みを作る

ここまでの内容を踏まえ、実運用で取り入れやすいメンテナンスの流れを整理する。

月に一度程度、以下の手順を実行するだけでストレージの肥大化を抑えられる。

# WSL内で実行:不要データの削除
sudo apt clean && sudo apt autoremove -y
rm -rf ~/.cache/pip ~/.cache/npm

# Dockerユーザーの場合
docker system prune -a --volumes
# PowerShellで実行:vhdxの圧縮
wsl --shutdown
wsl --manage Ubuntu --compact
wsl --manage docker-desktop-data --compact

これをスクリプトファイルとして保存しておけば、ワンクリックで実行できる。

また、sparseVhd=trueの設定を済ませておけば日常的な肥大化は軽減されるが、大量のDockerイメージを扱った後などは手動圧縮を併用するのが確実だ。vhdxのサイズを定期的に確認する習慣をつけておくと、突然Cドライブが逼迫する事態を防げる。

目次