Programmer Tips‎ > ‎

Shrinking VM Disk Images

posted Jan 12, 2012, 3:19 PM by Tyler Akins   [ updated Jun 8, 2012, 10:28 AM ]
I have been asked to compress dynamically-sized virtual disk images more than once.  These instructions can apply to VMDK files (common for VMWare) and VMI files (VirtualBox).  This sort of request seems to come up every year or two for me.  Usually it is because some place is gearing up to distribute these disk images and serving up gigs of data is undesirable.

I come up with the same sort of steps time and time again.  Instead of recreating this work for the next time I get asked, I'm posting these instructions online to record them publicly.  I've found that they are more thorough than what I find on other sites, so perhaps you could benefit from these instructions too.

First Step - Backup

Make a backup.  The steps below can really destroy images; follow them AT YOUR OWN RISK.

Reconfigure The Machine

Before you distribute the disk image around, you may need to tweak the configuration so that other virtualization tools will work with your image correctly.

Disable Network Configs Via MAC Addresses

If you use kudzu, you should disable it or it may prompt you when you start up the VM and it has a new MAC address.  Kudzu ships with older Red Hat and CentOS.

chkconfig kudzu off

Newer systems use udev.  You can disable the persistent network connections with these commands.

rm /etc/udev/rules.d/70-persistent-net.rules
cd /lib/udev/rules.d
rm 75-persistent-net-generator.rules && touch 75-persistent-net-generator.rules

You will also need to make sure you networking scripts don't have hardcoded HWADDR lines.

cd /etc/sysconfig/network-scripts
perl -pi -e "s/^HWADDR/#HWADDR/" ifcfg-eth*

Free More Space

It is a common misconception that deleting files on your dynamically sized disk image will make the disk image shrink.  This is not true - the virtual machine software doesn't peek into the filesystem to determine that sectors aren't needed any longer.  More on this later ...  For now, let's focus on making some room.

Delete temp files.  They shouldn't be needed.

# Linux variants
find /tmp /var/tmp -mindepth 1 -maxdepth 1 -exec rm -rf \{\}

If you are on Windows, you can usually delete the files in C:\Windows\Temp or use a program like CCleaner to thoroughly scrub away temporary files and unused garbage.

Clean your package manager's cache on Linux:

# Red Hat, CentOS
yum clean all

# Debian, Ubuntu
apt-get clean
apt-get autoclean

Also, you could clean out logs in /var/log.  This section could be improved - just let me know other things that could be cleaned out.

Defragment The Drive

This step really isn't needed, but it could help to squeeze out a few more bytes if you are really concerned.  There's really no defrag for Linux.  For Windows, I suggest using UltraDefrag.

Wiping Free Space

Even after you delete the files, the hard drive image still has the contents of the old file on it.  This is why programs like photorec can work.  We need to wipe the data clean off the drive by writing NULL (hex 0x00) bytes to all of the free areas on the drive.  This still doesn't make the image any smaller.  More on this later ...

Wiping Linux From CD

The easiest way to wipe extfs filesystems (ext2, ext3, ext4) is with zerofree.  It's the faster choice.  You can download the iso image of Parted Magic and configure your VM to mount that as a virtual CD-ROM.  Boot from it, then open a terminal by clicking on the black monitor icon at the bottom.  From there, it is a few simple commands:

# Wipe a hard drive partition.  Let's say that /dev/sda1 is for /boot and /dev/sda2 is /root
zerofree -v /dev/sda1
zerofree -v /dev/sda2

# Do you use LVM?  Don't forget that your device name may differ from mine.
# If you are unsure which device, look in /dev/mapper
vgchange -a y
zerofree -v /dev/mapper/VolGroup00_LogVol00

Now we can also wipe the swap.

# If swap is a normal partition ... make sure you know which partition it is!
# You can also use ddrescue or dd_rescue instead
dd if=/dev/zero of=/dev/sda3 bs=1M

# If you use LVM, the device will be under /dev/mapper instead
dd if=/dev/zero of=/dev/mapper/ bs=1M

Guarantee we're done and shut down.

shudown -h now

Wiping Linux From Itself

You can also use zerofree on the system if you prevent things from writing to the disk.  This is a bit more risky.

# Shut down to single user mode
init 1

# Remount the drive read only
# If you get errors, use "fuser -m /" to see process IDs that have open files
# Once they get killed or handled, then try this command again
mount -o remount,ro /

# Start wiping, assuming that the drive mounted to / is /dev/sda2
zerofree -v /dev/sda2

# Wipe the boot partition, assuming you have one and it is /dev/sda1
zerofree -v /dev/sda1

# Clear the swap space, assuming it is /dev/sda4
dd if=/dev/zero of=/dev/sda4 bs=1M
mkswap /dev/sda4

# Guarantee we did things

# Done.  Shut down the machine now!
shutdown -h now

Wiping Windows From Itself

There are a couple tools that I'd recommend.  First, CCleaner has added a built-in disk wiping utility.  It's easy to use.  Alternately, Eraser also is a nice tool with a GUI.  If command-line tools are more your thing, check out  SDelete from Microsoft's site, then open a command prompt and run it.

sdelete /c c

Wiping Linux By Filling The Disk

As a last resort, you can use "dd" to fill a disk.  I suggest you boot from a bootable CD image, mount your filesystem, then run dd.  That way you can prevent many bad things from happening.  Either way, you'd be executing commands such as this

cd /mount_point_I_want_to_fill
dd if=/dev/null of=empty_file
rm empty_file

Wiping Windows By Filling The Disk

It is better to not fill your hard drive with a big empty file, but these instructions are provided in case you really don't have a better way.

You can use nullfile to create this huge, empty file; Harddisk Image Cloning for PCs has links to the software.  I'd suggest using Control-F to find "nullfile" instead of scrolling.  All you need to do is double-click to run it.

There is also a Windows port of dd that works very similarly to the Unix version.  Open a command prompt and run these commands to fill your disk

dd if=/dev/zero of=empty_file bs=1M
del empty_file

Resizing The Disk Image

Finally, after we freed up lots of space and wiped the space with zeros, we can now shrink the image.  The virtualization software would have too big of a burden to resize the disk image on the fly to get smaller.  Maybe it can be smart and do this in the background someday, but for now we are forced to manually resize the file ourselves.  Here's all of the solutions I know about.  I haven't had any need to start VMs on Linux or MacOS, but the instructions below should be similar to your install.

VMWare Server's Utility - Windows Host

VMWare Server comes with vmware-vdiskmanager, which can shrink .vmdk files.  Open up a command prompt and run vmware-vdiskmanager.

"C:\Program Files\VMware\VMWare Server\vmware-vdiskmanager" -k my_disk_image.vmdk

VMWare Player - Windows Host

Open up VMWare Player and edit the virtual machine.  Select the hard disk, then there's a button on the right that says Utilities.  Under that drop-down menu is an option, "Compact".  Presto-chango, you are done.

VirtualBox - Windows Host

The VBoxManage command can use "modifyhd" to shrink .vdi files but there is no support for shrinking .vmdk files, which VirtualBox can also read and write.

"C:\Program Files\Oracle\VirtualBox\VBoxManage" modifyhd my_disk_image.vdi --compact

Alternately you can copy the disk to a new image, but this changes the UUID.  By changing the format parameter, you can change it to a VMDK file or other types.  When you do this, you'll need to go to VirtualBox and remove the old disk image and attach the new one, then you can finally delete the big disk image.

"C:\Program Files\Oracle\VirtualBox\VBoxManage" clonehd my_disk_image.vdi my_shrunken_image.vdi --format VDI


When Vagrant makes a new package, it will automatically clone the hard drive, which uses the virtualization software's process for copying a hard drive.  This won't copy the blank sections of the disk, making a smaller image automatically.