Building a Custom Drupal Image for Vagrant
Not too long ago, I posted a blog entry about 5 reasons for using a virtual machine for Drupal development. At the suggestion of some commentors, I have started looking into using Vagrant to manage my VMs. There is an excellent Drupal Vagrant project that provides a great starting point. This article explains how to begin with that and modify it to suit your own needs.
This isn't a detailed explanation, but rather a high-level roadmap to get you started developing your own site on Vagrant/VirtualBox. There are only a few short code samples, and most of the customization is left up to you. But as you'll see, Vagrant is designed to be easily modified. Once you've got an understanding of the process, the rest is (as they say) an implementation detail.
We want to...
- Continue doing development on the local box with our normal tools.
- Have a copy of the site running inside of a virtual machine.
- Be able to test in real time. Make a change, save a file, have it show up on the VM.
- Still allow version control tools to function normally.
Before beginning, you should install VirtualBox and Vagrant, and grab a copy of the Drupal Vagrant project. (WARNING: I tried this on 64-bit Windows 7 and it does not work because of bugs in JRuby. AFAIK, it works on all other supported platforms.)
Follow the instructions (README.markedown) to install and create a Drupal Vagrant box. Make sure it works. Once you are sure, type
vagrant destroy to destroy your VM (this will stop the server and then delete it).
For this article, I will assume that your Vagrant instance is in
Warning (and consolation): Vagrant and its deployment system (Chef) are written in Ruby. Many of the files you will encounter are actually Ruby source code. But don't worry, you don't really need to know Ruby to do this stuff. The high-level libraries that Vagrant and Chef provide make the files feel more like configuration files than scripts.
Step 1: Create a New Role
vagrant/roles, there are a handful of ruby files that define "roles". In a nutshell, rolls are sorta like installation profiles. They allow you to tell Vagrant what sort of system you want it to build (what role it will play).
Take a look at the role called
drupal_lamp_varnish_dev.rb. That is the default role for Drupal Vagrant. It's a good place to start, so copy that into
This file gives Vagrant a list of roles and recipes that will be run.
name "lamp_varnish_drupal_dev" # Change this to 'myrole' description "A LAMP + Varnish + Memcached stack for Drupal similar to Mercury with development tools." run_list( "role[apache2_mod_php]", "role[apache2_backend]", "role[drupal]", "role[drupal_dev]", "role[memcached]", "role[mysql_server]", "role[varnish_frontend]", "recipe[drupal::drupal_apps]" )
There are things to note about this:
- Roles can run other roles. In that way, you can chain together different roles to build new profiles.
- Recipes are particular instructions for doing something. More basic roles have
run_listsmostly comprised for
This will be your basic role. You will add and remove things from it as necessary.
Right now, all you need to do is change the name to 'myrole' and save it.
Step 2: Update your Vagrantfile to use the new role.
/vagrant, there is a file called
Vagrantfile. This is the master build profile, and it is the first thing Vagrant reads when building a new machine.
Edit it and look for a line that says
chef.add_role('lamp_varnish_drupal_dev'). Change it to load your new role:
Now the next time you do a
vagrant up, it will determine what kind of system to build by consulting
Step 3: Create a cookbook
In this configuration of Vagrant, we are using Chef. Chef is a build system that uses cookbooks -- collections of recipes -- to deploy a system.
In our case, we will be creating various recipes, and we need a place to put those.
So create the directory
vagrant/cookbooks/custom-cookbooks. You can store your own cookbooks in here. Let's create one called
$ cd vagrant/cookbooks/custom-cookbooks $ mkdir -p mysite/templates/default mysite/recipes
That will create a new cookbook called
mysite with a couple of directories in it:
templates directory is for template files. The
recipes directory is for recipe scripts.
Step 4: Create a recipe
Recipes in Chef/Vagrant are short Ruby scripts written in Chef's domain language. If that sounds daunting, don't worry. The fact of the matter is that in most cases, you can learn just a few patterns and apply them with great success.
By far, the best place to start is with the
vagrant/cookbooks/drupal-cookbooks/drupal/recipes/example.rb recipe. This builds out a new Drupal site from scratch, configuring the database and using Drush Make to build a pristine site.
example.rb file into your own
mysite cookbook and start working on it. You also should add this line to your
myrole role at the end of the run list:
recipe[mysite::example.rb]. (Optionally, you may want to remove the line
chef.add_recipe('drupal::example') from the
Vagrantfile. By default, Drupal Vagrant loads its own example recipe.)
Take some time to look at the
example.rb file, and play around with it. Use
vagrant up to create a new server. In most cases, instead of destroying and rebuilding, you can update a site to the latest file changes you've made simply by doing
vagrant provision. And you can ssh to your site doing
(One noteworthy section of
example.rb is how it executes SQL commands. You can tweak that section to load a dumped DB file, should you so desire.)
Step 5: Linking your local (host machine) Drupal installation with your Vagrant box.
There are many things you will likely want to tweak and tune in Vagrant, and an entire book could be written on the topic. But here is one thing you are quite likely to want to do: Link your local dev environment to your Vagrant box.
Doing this is a two-step process:
First, in the Vagrantfile, you should add this:
config.vm.share_folder("my_site", "/var/www/my_site", "/full/path/on/your/local/dev/drupal")
This configures your VM to link its
/var/www/my_site folder to the local directory you supply.
Second, you need to tell Apache to use your site as a docroot. There are a few ways of doing this, but I find the most effective to be copying the
vagrant/drupal-cookbooks/drupal/recipes/drupal_apps.rb recipe and the
vagrant/drupal-cookbooks/drupal/templates/default/sites.conf.erb templates into their respective locations underneath your new cookbook, and then altering the
docroot value in
docroot should point to
var/www/my_site. (Basically, your build an Apache virtual host file with this template.)
Once you've done that, edit your
myrole.rb role file, and change it from running
At this point, you should have a stable virtual machine whose doc root is synced with your local development environment. You should be able to continue using your chosen IDE (though you might need to configure the debugger),
svn, and whatever other development tools you use.
There is much, much more that can be done with Vagrant. Here we've barely scratched the surface. But I hope this helps get you started.
Reading the included recipes will help you make that next step. Here are a few more resources that you should read or use as reference:
Updated: Added a link to the original 5 reasons post.