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ファイルは膨らんだままになる。
以下の図は、この仕組みを示したものだ。
つまり、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ドライブの容量を気にせず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 --manageやdiskpartで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ドライブが逼迫する事態を防げる。