Programmers: VirtualBox is a better Development Environment

You may ask why use an Oracle (formerly Sun) VirtualBox (VBox) Virtual Machine (VM) for a development environment when coding? From the perspective of a developer on your team, the answer is, for several reasons:

  • We can have the same development environment regardless of our desktop environment.
  • We set the VM to 512mb memory to start, which is like the remote VPS server environment. This is nice because you can scale memory and/or cpus up or down at will, and instantly with a few clicks. A great way to test your application under various loads.
  • By starting the hardware resource limits low (mem and cpu), we limit how greedy the stack can get. If the vm freezes, the rest of your system does not.
  • Starting with constraints forces us to build efficient code from the start, instead of refactoring for efficiency later (which realistically never happens). The same is true for bugs affected by the environment, which previously you would only encounter once you attempted to deploy to a remote development or production server. When you are deploying to production, that is too late to be finding out you have bugs related to environment differences.
  • With VMs you can take snapshots of the hard drive at any given point in time. Snapshots taken thereafter are similar to version control in that only the differences are actually saved. So it’s efficient, quick, which means less expensive. When you mess something up with the install or environment you can just roll back to a time when everything was working.
  • The use of snapshots can become like a form of unit testing. You can make copies of working environments to start new projects. You can test source code (e.g. from outside the VM over a mounted vboxsf or nfs share) in different points of the snapshotted environments.
  • Also, consider your other projects not in a VM. When you need to switch gears, you just start or stop another VM. It takes a few seconds, and you can be running several different versions of Apache, PostgreSQL, Ruby, PHP, and all other sorts of programming tools. This gives you precision in developing. No longer do you have to hold back to the old verisons of software in order to stay compatible with all projects. You can develop your applications on the bleeding edge of technology. And save resources by only running the tools you need when you need them.
  • Once you get the vm setup correctly, you can quickly send the entire environment to your peers. For teams on a gigabit LAN, the time to transfer a typical 1GB virtual disk image (*.vdi) is trivial. For teams across the planet, preparing instructions like the ones below are often faster and take on average 1-2 hours to complete. Not to mention if you put it on a USB drive you can take it with you anywhere you go.

There are more benefits as you will see through using it, but you’ll need memory; at least 1.5-2gb is preferable. Less is technically possible but you’ll see performance hit depending on the size of your VM.

Ultimately, the result for those using the vm image is an instant development environment, with no dependency conflicts, configuration quirks, or hardware differences. On average with this I have new development team members able to join the team brand new and start contributing meaningful code in as little as 6 hours on average, versus 24-32 hours for the non-vm approach. But with the non-vm approach you have to consider all the problems you face down the road that end up beingĀ  environment differences.

Below is a pseudo bash script outlining how to prepare one of these virtual machine images (*.vdi) using Ubuntu 10.04 (Lucid Lynx) 64-bit.

UPDATE: I haven’t used this script in a few months now; I found it easier to make a base image and use the `VBoxManage clonehd` cli command to copy and modify. There are numerous reasons for this but among them: its faster, its easier, it has all the latest updates including any quirky setup preferences you may have at the time. But the script below is still good for getting your first few images started.

# download an ISO of Ubuntu 10.4 LTS Server
# NOTE: If your pc is 64-bit and can emulate 64-bit VMs get that one. If not, use the i386/32-bit iso

# download and install latest VirtualBox (3.2.4 r62467)
# run VirtualBox
# click Machine > New (Ctrl+N)
# click Next
# type Name:
# select Operating System: Linux
# select Version: Ubuntu (64 bit)
# click Next
# click Next # keeping memory at 512 MB, the default
# click Next # to "Create new hard disk", the default
# click Next
# click Next # for "Dynamically expanding storage", the default
# click Next # for 8.00 GB size, the default
# click Finish
# click Finish

# right-click on new vm for context menu
# click "Settings... (Ctrl+S)"
# click "System" > "Motherboard"
# uncheck "Floppy'
# click "System" > "Processor"
# check "Extended Features:" "Enable PAE/NX"  # very important or you will get errors with Ubuntu Lucid
# click "Storage"
# under "SATA Controller", right-click on the .vdi and chose "Remove Attachment"
# right-click on "IDE Controller", choose "Add Hard Disk", and then select the .vdi file you just removed.
# This is because you have to use IDE; SATA is broken at the moment.
# under "IDE Controller", highlight "Empty" and ensure the right "Slot:" says "IDE Secondary Master"
# click the yellow-folder-with-green-up-arrow icon to the right of "CD/DVD Device:" to open the Virtual Media Manager
# click "Add" toolbar icon button to open the file browser dialog
# browse to and select your Ubuntu 10.04 Server .iso
# click Open
# click OK
# NOTE: sometimes at this point there is a bug in VirtualBox where the left menu that used to show General, System, Display, etc. is now collapsed. To fix you have to close the window and repeat steps to select .iso
# click Audio
# uncheck "Enable Audio"
# click Network
# select "Attached to:" "Bridged Adapter"
# NOTE: click "Advanced" and make note of the Mac Address if you need to have it added to your router. I prefer this way because I have mac address filtering enabled on my router.
# click USB
# uncheck "Enable USB Controller"
# click OK to close the window and save all your settings changes

# highlight the vm and click Start tollbar icon button

# when Ubuntu setup boots, it prompts you to select your language, with English being the default
# select language as you wish (e.g. English)
# press F4 at main menu and select "Install a Minimal Virtual Machine" then press enter twice to begin installation
# answer localization questions as you wish (e.g. US Keyboard)
# if asked, select "Do not configure network at this time"
# hostname can be whatever u like (e.g. development)
# chose your time zone
# choose "Guided - use entire disk"
# choose NO to "Encrypt my home directory" when prompted; it causes problems with keys
# choose "no automatic updates" when prompted
# do NOT choose any software to install when prompted, instead hit TAB and ENTER to skip
# YES to install GRUB bootloader
# CONTINUE to reboot

# once booted to prompt, login
sudo -i # become root
# NOTE: wherever you see the username 'mikesmullin' replace with your own in these instructions
# install ssh
aptitude install openssh-server
logout # of root
logout # of your user
# outside the vm, i also prefer to add a host entry for mysite.local to my /etc/hosts

# from outside the vm, ssh into the machine from now on
ssh mysite.local
sudo -i
# change line 28 to read:
rm /etc/motd
logout # of root
logout # of your user

# now would also be a good time to install your ssh key
# so you don't have to type your password every time you ssh into the vm
# from your localhost (outside vm):
ssh-copy-id -i ~/.ssh/ mysite.local # this assumes you already have generated an rsa ssh key

# install vbox guest additions
ssh mysite.local
sudo -i
aptitude update && aptitude safe-upgrade
reboot # to switch to latest kernel

# once vm is rebooted:
ssh mysite.local
sudo -i
aptitude install linux-headers-virtual build-essential psmisc wget vim
#aptitude install xserver-xorg xserver-xorg-core # NOTE: uncomment this for 32-bit systems
# in the vm window
# switch focus to the window entitled "[Running] - Oracle VM VirtualBox"
# click Devices > Install Guest Additions... (Host+D or RCtrl+D)
# NOTE: for some people the menubar at the top of that window is gone. if this is you, you can still use the keyboard shortcuts above and use the arrow keys left/right to switch menus or up/down to make your selection
# now resume from your ssh terminal:
cd /media && mkdir cdrom
mount /dev/cdrom cdrom && cd cdrom

# once vm is rebooted and at login prompt,
# at this point it is a good idea to make a snapshot of the virtual machine:
# switch focus to the window entitled "[Running] - Oracle VM VirtualBox"
# click Machine > Take Snapshot... (Host+S or RCtrl+S)
# name the snapshot "fresh ubuntu install"
# this way you will always have this point to roll-back to if you manage to mess up the next steps
# feel free and please remember to make as many snapshots as you like; you can never have too many, only too few.
# now resume from your ssh terminal:
ssh mysite.local

# setup src
# add your localhost directory containing your src code dir to vbox vm as a permanent shared folder named 'src'
sudo -i # become root
cd /media && mkdir src
echo "src   /media/src      vboxsf  rw,uid=1000,gid=1000    0       0" >> /etc/fstab
mount -a
# NOTE: If you get the following error, go to vm Devices > Shared Folders...
#       and make sure you add the ./src dir and check "Make Permanent"
#       then run above cmd again.
#   /sbin/mount.vboxsf: mounting failed with the error: Protocol error
cd /var/www && ln -s /media/src src && cd src

3 thoughts on “Programmers: VirtualBox is a better Development Environment

  1. Eric

    What an awesome post Mike! I used your settings to setup a Ruby on Rails environment for a side project and it was as simple as 1, 2, 3!

  2. Pelle

    Great post. I love using vbox for my test environements at work. But i have not yet figured out a good way to version control my snapshots and all it’s app config files in them. What I want to do is basically be able to get a readable svn diff between my different snapshots. But I can’t figure out a nice way to do it. Any ideas?

  3. Vasudev Ram

    Very interesting and useful article. Hadn’t come across this idea before, though, of course (not to take away any credit from you), given the features of virtualization, it seems obvious now (with hindsight :-) . I saw this article via a comment in Satish Talim’s Online JRuby 101 course on Google Plus.

    Thanks for posting it,

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>