How can we make our Vagrant VM image smaller?


(Jeff Atwood) #1

The current Vagrant virtual machine development model is working great, as documented here:

http://blog.discourse.org/2013/04/discourse-as-your-first-rails-app/

However, one part is kind of a pain – the massive download of the initial VM image.

http://www.discourse.org/vms/discourse-0.8.4.box

This file is 891 MB. And after Vagrant works its magic, it goes to 3GB.

This is basically a Linux Ubuntu image, with the necessary dependencies pre-installed for Discourse development:

  • Ruby
  • Rails
  • Postgres
  • Redis

… and so forth.

Is there any way we can compact, resize, or otherwise make this VM image smaller so it is quicker and easier to download for folks that want to get started with Discourse development?

891 MB is a lot of downloading before you can get going on Discourse. Would love to make this VM smaller if possible!


(Yaw Anokwa) #2

Use python-vm-builder and some shell scripts to build the VMs and they’ll end up being 100-300mb zipped. I can provide some sample scripts upon request…


(Jeff Atwood) #3

Well I figured out a few things.

The .box file is a .tar archive containing these files:

box-disk1.vmdk       954 MB
box.ovf               15 KB
vagrantfile            1 KB

Importing this into VirtualBox results in a disk file of

box-disk1.vmdk       2.8 GB

So ideally what I want to do is try compacting this image as documented here:

http://splatoperator.com/2012/07/compacting-a-vmdk-virtual-machine-disk-format-image/

Compacting a VMDK file (.vmdk) is a good idea if you want to share or reuse it, such as with Vagrant. If you’ve tinkered with your VM a bit, deleting cached files isn’t enough. The space in the filesystem is marked as free, but isn’t erased. It still contains the data, so it doesn’t compress as well. Here, I’ll describe how to zero that free space and shrink that image.

How much it helps depends on your disk content, but for what it’s worth, my VMDK with an Ubuntu Maverick 64 install shrank from 2.0GB to 1.6GB, and gzipped they are now 679MB and 425MB, respectively.

Don’t have time to get further at the moment, but that would help.


(Jeff Atwood) #5

OK, that did seem to help; after cloning the drive I see:

previous.vmdk    2,777,024 KB
cloned.vmdk      2,386,688 KB

So a 15% size reduction for “free”. I’ll take it!

Items #1 is sort of outside the scope of what we can do right now, but for future VMs we will definitely try to start with a smaller distro if possible.

Items #4 and #5… I don’t think the required .box vagrant file format allows us to manipulate compression type and so forth, does it?


(Peter Bowyer) #6

There was a recent thread on Hacker news that may help: Ubuntu low-memory install for VMs


(Jeff Atwood) #7

Well, this is about optimizing for disk space, not memory. We’re not concerned about the memory footprint of the VM, just the disk footprint.


(Jeff Atwood) #8

OK, the plot thickens. Looks like the VirtualBox “export appliance” packaging is really hurting us, size-wise.

When I import these files into VirtualBox…

box-disk1.vmdk       954 MB
box.ovf               15 KB
vagrantfile            1 KB

Using the “Import Appliance” menu on the box.ovf file…

I get these files:

box-disk1_1.vmdk            2,776,896 kb
discourse_1363817576.vbox          10 kb

If I use 7zip “normal” compression on that box-disk1_1.vmdk file I get:

box-disk1_1.vmdk       563 MB

That is a considerable savings over:

discourse-0.8.4.box    891 MB (tar + gzip)
box-disk1.vmdk         954 MB (gzip)

So we could save nearly 40 percent in file size if we could somehow use 7zip to compress the drive image of the virtual machine… I’m just not sure how to get it in there in a way that Vagrant can understand?


(Rafe) #9

@peterbowyer’s link is basically the same advice @yanokwa gives in item #1. Tiny distro = less stuff installed on the image and thus less stuff loaded in memory. Read the source article for the results:

Instead of “Normal” select “Install a minimal virtual machine”. As far as I can tell, this has little to do with being a virtual machine. Instead, what this option means is “use the least RAM possible”, as well as " reduce disk usage".

The mini installation uses 680-megabytes of drive space, whereas the full installation uses 1.1-gigabytes of drive space. The changes in memory usage are more dramatic. The mini installation takes 51-megabytes. The full installation takes 561-megabytes.


(Jeff Atwood) #10

I see, that makes sense – apologies, I just saw “low memory” and assumed it was for machines with 2GB of memory trying to run VMs, or something like that.


(Peter Bowyer) #11

@Rafe thanks for explaining it. I was trying to help with how to get the small distro to start with. There’s a few more options mentioned in the comment thread, in addition to the “install a minimal virtual machine” option:


(teadriven) #13

We produce a kiosk image for deploying our systems and take a different approach. It is a cut-down Ubuntu image that is maintained in a VM (VirtualBox) but we actually produce an ISO instead. This has the advantage that it can be installed in any VM or on a physical system.

The steps involved are:

  1. Remove unnecessary packages from a basic Ubuntu install.
  2. Whenever it has been updated make sure to clean up the package downloads with “sudo apt-get clean”.
  3. Shutdown the VM and then run a backup script on the host.
    a. Mount the virtual disk.
    b. Archive the contents (excluding proc, sys, mnt, media and dev) using something like tar.bz2.
    c. Create an ISO using a minimalist OS designed to run from CD (we use ploplinux).

It is relatively straightforward to customise something like ploplinux to boot straight into an install script that will create a partition, extract the image archive and update grub.

The ISO is created using mkisofs found in the genisoimage package.

With this method we are able to produce ISO images that are around 260MB in size. Our systems are designed to run headless and therefore the image does not contain a desktop environment which greatly helps to reduce the size.

The ISO can then be burnt to CD, used to create a bootable USB stick or mounted directly within a fresh VM of your choosing.

I’m not saying that you necessarily should do it in the same way, but hopefully our approach might give you some ideas.

EDIT: Also bear in mind that the kernel and associated packages are quite big, so make sure that all but the latest kernel have been purged from the image before archiving.


(VStetskevych) #14

If your aren’t wiping the free space before box creation, you should.
I have used veewee to create my VM templates, and it includes wiping operation. Veewee did need a little customization of it’s scripts, for my purposes. GitHub - jedi4ever/veewee: Easing the building of vagrant boxes
Another thing is to check if you have unnecessary stuff installed. Ubuntu is pretty bloated. Check for any X11 packages, for a start.


(Peter Nikolow) #15

I am still downloading the VM image - so far 10% and 3 hours remain…

My idea is to make VM image as smaller as possible and once user import it on VirtualBox to start one shell script that will do rest - apt-get update && apt-get upgrade and installing everything as is needed.

This will avoid the downloading image and then first update to download 1G of “updates” because some packagees went old. I think that if we have good luck we can hit 100MB barrier as initial VM image.


(James P) #16

The smallest way of course is going to use sprinkle/chef/puppet to install everything on a blank vm like the Ubuntu open box above.


(Jeff Atwood) #17

I opened an issue on the Vagrant GitHub and got a response:

This is absolutely possible. Since Vagrant 1.1, under the hood it is just shelling out to “bsdtar” which is packaged with every installer. bsdtar actually has the capability to handle 7-zip files. I’m not sure if I currently compile it with that capability but I’ll have to check. Also, I’ll have to verify that bsdtar is compiled with 7-zip support for Windows, since that was compiled outside of my control.


(Michael Brown) #18

The version of bsdtar shipped with vagrant 1.2.2 isn’t compiled with 7z support.

Perhaps I can offer this as a work-today stopgap:

$ du -ms discourse-0.8.4.box.7z 
549	discourse-0.8.4.box.7z

I’ll upload it from work tomorrow. I tried uploading it from home and I’m getting… 30KBps. Yay DSL.


(Jeff Atwood) #19

Great! Provided this still works with

vagrant up

Per our instructions that is fine.


(Michael Brown) #20

It will after it’s unzipped! I’m also amending our instructions with some of my notes & experiences.


(Willian Arantes) #21

Hey Guys! Have you got any progress on this subject?
Thank in advance.


(Michael Brown) #22

Down in size to less than a CD is pretty decent, I think.

Are you having difficulty with the size as-is?