Ideally, we should all be developing our code in our own little space on our little local server. This allows us to easily make changes without messing up production code or stepping over other's work. This is usually cost prohibitive so we use virtual machines to make this a reality.
The problem we face is that each developer needs to have a virtual machine that is setup exactly (or nearly exactly) like our production server. This requires a long list of configuration changes that need to be made on every machine. For example, install the apache package, update this configuration file, setup Samba so you can access the files remotely. Then we run into more problems when additional changes are needed because the developer has to take time out of their schedule to make them on each machine. There are also passwords that have to be remembered and /etc/host changes that need to be made. You'll be in even worse shape if the deployment consists of multiple VMs.
Scott's Note: This is still a valid post but I suggest you read Getting Started With Vagrant Using PuPHPet.com for a slightly easy approach that doesn't require as much command line work and is easier (in my opinion) to work with.
Vagrant is here to help us make this process easier. With Vagrant we can easily create a VM with all the packages and items we need in order to get our project up and running. It will then, just as easily, allow us to delete the virtual machine so we don't have it eating up space on our computer (with the cost of hard drives being what it is this argument might be completely academic).
The real benefit is that you will no be a slave to the "it works on their computer" excuse. This is a total cop out and really only hurts your internal and external customers. Because every development box has exactly the same configuration (or can in a matter of minutes) this extra variable is removed when it comes time to fix a bug.
On top of that Vagrant gives us some other really cool features. The best one in my opinion is that it automatically redirects your working directory to the /vagrant directory on the VM. That means you can use all your native applications (GitHub for Windows/Mac, Sublime Text 2, MySQL Workbench, etc.) and truly work the way you want to work.
If you don't already have it installed install VirtualBox and Vagrant. I'll also be using a copy of Wordpress as an example or you can download all the code for this setup from this github repository https://github.com/warren5236/WordpressWithVagrant/tree/UsingBootstrap.sh.
The first step in a new project is to run
This will create a Vagrantfile in the current directory and configure it with the default settings to use a 32-bit Ubuntu Precise Pangolin (12.04). You can look at the Vagrantfile in any text editor but we're going to replace it with the following:
It may look complicated but it's really not. The second and third lines specify the name of the VM and where to get it's base file. The fourth line forwards port 8080 on your machine to port 80 on the VM. The fifth line specifies a file named bootstrap.sh (also located in your root directory but feel free to move it else where) which will be run every time you boot the VM.
This script is going to contain all the commands that will setup our VM to be in the state we need it. This could all be done with Chef or Puppet but I don't think it's necessary for such a simple setup.
Installing MySQL, PHP and Apache
The first thing we want to do is install MySQL Server, PHP, and Apache so Wordpress has it's requirements. Luckily, Ubuntu has all of these in packages already so we can just install them directly. Unfortunately, the package for MySQL prompts you for a password and we want this to be a completely hands off experience. The first two lines in the commands below set the password for installing MySQL, the third line updates apt-get's list of packages (you can run into "missing" packages if you skip this step), and the fourth line installs everything we need.
Creating the database settings
The next section of the bootstrap.sh file looks like this:
Because this script will run every time the VM boots we need to make sure that the process for creating the database and the database user will only run once. To do this we touch a file name /var/log/databasesetup and if the file exists we skip over this part. The section at the very bottom checks to see if there is an initial data file and restores it to the database. I'll go over this more later in this article.
The last thing we need to do is to configure Apache:
We're doing a similar trick to the one above but in this case we're checking to see if a symlink exists and then we're remapping the public directory in our repository to the /var/www directory (the default document root), enabling mod_rewrite (for permalinks) and then allowing the use of .htaccess files (also for permalinks).
The complete file
This is what the complete file should look like:
Because we have the root MySQL password listed in the
Vagrantfile we're going to want to protect it from prying eyes. The best way to do this is to keep it outside the directory that Apache is going to be serving. To do this we're going to create a public directory inside our working directory and then put all the Wordpress files there. If you looked closely in our bootstrap.sh file you'll notice that this is where we redirect /var/www to. When you're done it should look something like this:
Now it's time to create the VM. Type
vagrant up into the command prompt in your project directory (the one with the Vagrantfile in it) and you'll get the following:
[Shortened so people don't go insane]
At the end of this you'll be brought back to the command prompt and if you attempt to access http://localhost:8080 on your computer you should see the Wordpress install screen:
Now that we have Wordpress up and running it's time to make a copy of our database so we can easily restore it the next time we need to created this virtual box. In order to do that we need shell access to the server. Type the following into the command line:
This will automatically log you into the VM and you should see something like the following:
Now that you have direct access to the VM. Feel free to play around all you want. Remember that anything located in the /vagrant directory is mirrored to your working directory so you can damage it but everything else can easily be restored.
When you're done run the following commands mkdir /vagrant/data mysqldump -uroot -prootpass wordpress > /vagrant/data/initial.sql
This will make a backup copy of our Wordpress database so we can easily restore it the next time we recreate the VM.
Just to make sure everything is working we can look at our working directory and see that the sql file has been stored.
In order to leave the SSH session just type in
The VM isn't just idle. It's actually using some memory and CPU cycles just sitting there. So we don't tax our system too much we can shutdown VMs when we aren't using them. This is done using the
vagrant halt command.
If we open VirtualBox before issuing this command we'll see that the VM is running:
When we run the command we'll see the following in the command line:
Then if we look back at the VirtualBox window we'll see this:
When we need to use this VM again we can just run
vagrant up and it will be booted.
If you're like me you have a lot of projects going all the time but you don't always have enough room on your laptop hard drive for them. So from time to time you'll need to clean out the older images. In order to do this we'll use the
vagrant destroy command. When we issue this command the following should be displayed:
After this has run we can check in VirtualBox to see that the VM is no longer there:
I would actually recommend trying this occasionally even if you don't need to because it provides you with an "opportunity" to test your backups.
Vagrant Up Again
A couple months go by and our client want something changed. Thankfully we're using vagrant so we can quickly get up and running again. All we have to do is run
vagrant up again and the site will be restored to exactly the state it was in when we created the backups of the data. If you don't trust me try it.
As you can clearly see Vagrant provides several features that I think will make it a mainstay in everyones toolkit for years to come. It may be lacking in a nice user interface but it keeps me from having to repoint my root document as I switch projects or building 800 VMs. I've started using it for all my current projects and I'll be using it in any of my future projects as well.