Ubuntu on VirtualBox の可変サイズディスクを縮める
対象バージョン
- VirtualBox 6
- ゲストOS : Ubuntu18.04
- ホストOS : Windows10
VirtualBoxの可変サイズディスクを小さくする
VirtualBoxの可変サイズディスクはゲストOSのディスク容量に合わせて大きくなります。 ただし可変サイズディスクは拡張のみで、ゲストOSのディスク使用量に合わせて縮小することはありません。
場合によっては想定以上にディスクファイルが大きくなり、ホストOSのディスクを圧迫する恐れがあります。

幸いVirtualBoxには可変サイズディスクを小さくする機能があるのですが、利用するには下準備が必要です。
- zerofreeをインストール
- 不要な巨大ファイルを削除
- ファイルシステムをリードオンリーに変更
- recovery modeでzerofreeを実行
- ファイルシステムを戻してシャットダウン
- VBoxManageコマンドで可変ディスクを圧縮
zerofreeをインストール
zerofreeは空き領域をゼロクリアするツールです。
VBoxManageコマンドのディスク圧縮は、ゼロクリアされた領域に対してのみ有効です。 そのためゲストOS上の空き領域を事前にゼロクリアする必要があります。
zerofreeのインストール
sudo apt install zerofree
不要な巨大ファイルを削除
findコマンドで巨大なファイルを探す
sudo find / -size +500M
/swapfile
...
# proc以下は実体のないファイルなので、削除は意味がない&削除できないので注意
/proc/kcore
find: ‘/proc/28311/task/28311/fd/6’: そのようなファイルやディレクトリはありません
...
swapfileを削除したい場合は、swapoffコマンドでswapを止めてからファイルを削除します。 /etc/fstabにswapfileのマウント設定が書かれている場合は、そちらも削除します。
swapfileを削除
sudo swapoff /swapfile
sudo rm /swapfile
# swapfileのマウント設定を削除する場合
sudo vim /etc/fstab
...
/swapfile none swap sw 0 0
swapfileサイズを小さくしたい場合は、削除後にもう一度swapfileを作成します。
500MBのswapfile作成
sudo dd if=/dev/zero of=/swapfile bs=1MB count=500
500+0 レコード入力
500+0 レコード出力
500000000 bytes (500 MB, 477 MiB) copied, 0.220918 s, 2.3 GB/s
sudo chmod 600 /swapfile
sudo mkswap /swapfile
スワップ空間バージョン 1 を設定します。サイズ = 476.9 MiB (499994624 バイト)
ラベルはありません, UUID=96dfc4c3-6d8e-4385-813a-56a9344cb96a
sudo swapon /swapfile
ファイルシステムをリードオンリーに変更
zerofreeを実行するために、一度ファイルシステムをリードオンリーでマウントし直します。 再起動時にリードオンリーでマウントされるように、/etc/fstabを書き換えます。

容量を縮めたいマウントポイントのoptionsをnoatime,roに変更します。 後ほど設定を元に戻すので、最初に書かれていた設定は必ずメモしてください。(errors=remount-ro)
optionsをnoatime,roに変更
sudo vim /etc/fstab
...
# <file system> <mount point> <type> <options> <dump> <pass>
# / was on /dev/sda1 during installation
UUID=xxxxxxxxx / ext4 noatime,ro 0 1
# リードオンリーだけならroで十分だが、ディスクアクセス速度向上を願ってnoatimeも一緒に付与
mountコマンドで変更する方法もあるのですが、ディスクIOが走るプロセスをすべて停止させないと変更できません。 自分も最初は色々プロセスをkillして試していたのですが、結局fstabを編集する方法が一番手っ取り早かったです。
recovery modeでzerofreeを実行
zerofreeはUbuntuのリカバリーモードで実行します。 一度ゲストOSを再起動して、VirtualBoxのスプラッシュが表示されたらESCキーを連打します。 GRUBが表示されたら、Advanced Options for Ubuntuを選択します。

Linuxカーネルバージョン毎のリストが出るので、最新バージョンのrecovery modeを選択します。

リカバリーメニューにfilesystem state: read-onlyの表示があれば、 リードオンリーでマウントされています。 問題なければrootを選んでシェルを起動します。

リードオンリーにした対象マウントポイントに対してzerofreeを実行します。 今回はfstabのコメントにあった# / was on /dev/sda1 during installationのとおり、/dev/sda1を指定します。
zerofreeの実行
zerofree -v /dev/sda1
zerofreeは時間がかかる場合もあるので、終了するまで焦らずお待ちください。
ファイルシステムを戻してシャットダウン
zerofreeが終了したらfstabの設定を元に戻します。 fstabを編集するために、mountコマンドでread-writeモードにリマウントしなおします。
read-writeモードにリマウント
mount -o remount,rw /
optionsを元に戻す
vim /etc/fstab
...
# <file system> <mount point> <type> <options> <dump> <pass>
UUID=xxxxxxxxx / ext4 errors=remount-ro 0 1
fstabを元に戻したら、poweroffコマンドで仮想マシンの電源を落とします。
poweroff
poweroff
ホストOS上でVBoxManageを実行する
今回ホストOSはWindowsなので、コマンドプロンプトからVBoxManageを実行します。
コマンドプロンプトは、Windowsキー + rでファイル名を指定して実行を開き、「cmd」を指定すると起動します。

VBoxManage modifyhdを実行して、仮想サイズディスクの圧縮を行います。 圧縮対象ディスクファイルのパスは、VirtualBoxマネージャーのストレージで確認できます。
Windowsコマンドプロンプト
C:\Users\unio> cd "C:\Program Files\Oracle\VirtualBox"
C:\Program Files\Oracle\VirtualBox> VBoxManage modifyhd "C:\Users\unio\VirtualBox VMs\ubuntu18.04\ubuntu18.04-disk001.vdi" --compact
コマンド終了後、ファイルサイズが小さくなっていれば成功です。