Development, testing, staging and production — this is how most people devide up different environments for application development.
Maintenance and setup of these environments is often not a trivial goal to achieve. Having worked with a couple different code bases and setups over the last decade, I often noticed things like environment specific hacks (if ($env == 'testing') { ... }
) in application code and service configurations and a lot of manual labour all around. It's still very common that code deployed to staging does not work — but it worked for you right?
And it's also too common that members of a team do not know how something works because whoever set it up is currently out sick or on vacation.
My opinion is that the best setup currently available is something like: chef(-solo) on the server and Vagrant on the desktop. Something like because aside from chef, there is also puppet, cfengine and a couple others. Leaving specific projects aside, it really just boils down to automation (within reason).
Automation in my opinion is not just the easiest but the only viable way to setup development, testing, staging and production environments. Without some automation in place it's required that all team members know how all of it works when maybe that is not yet important and the end goal is that all environments actually resemble each other.
Enter Vagrant
Vagrant is a very nifty toolkit to bootstrap Virtualbox images. Bootstrapping means installing your application stack into one or multiple virtual machines in order to resemble production a lot better.
So a lot of times when I rave about how useful Vagrant and chef are, I get the crazy eye from PHP developers:
You want me to learn Ruby to setup my local development environment?
My response:
- Do not fear the Ruby.
- You don't have to. (Well, not a whole lot!)
Real talk
First off, of course you need Virtualbox — get a download from their website or use your package manager.
Then, it's not possible to avoid Ruby a 100% — after all Vagrant is written in Ruby.
When you're on a Linux or a Mac, this is usually enough (you may need sudo unless you RVM):
$ sudo gem install vagrant
For a sudo-less install, use RVM:
$ sudo gem install rvm
...
$ rvm install
...
$ rvm use 1.8.7
...
When set up, this is what you do:
$ gem install vagrant
...
RVM allows me to run multiple versions of ruby side by side and also leverage local gem installs — per Ruby version. Think of it as a nifty way to run multiple PHP versions and have a PEAR install per version — similar projects exist for PHP today:
To learn more about RVM, visit their website.
Once vagrant is installed, we can continue!
ShellProvisioner for fun and profit
So, in case you are more comfortable writing some shell script for the time being — Vagrant got you covered!
First off, create a new Vagrantfile
for your project:
$ mkdir -p Documents/workspaces/blog-example/
$ cd Documents/workspaces/blog-example
$ vagrant init lucid64
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.
lucid64
(Ubuntu Lucid 10.04, 64bit) is the name of one of my local box files for Vagrant. In case you haven't got a box yet, head over to vagrantbox.es. There are a couple images you (aka box files) you can download. To get the lucid64
box, use the following command:
$ vagrant box add lucid64 http://files.vagrantup.com/lucid64.box
Once you made it past vagrant init
, you should have a Vagrantfile
with a lot of stuff in there.
While it's not important for my tutorial, I recommend you review it some (other time). The created Vagrantfile
contains examples for all the provisioners (puppet, chef and shell) and a couple other configuration options, etc..
Let's skip over this and get to the ShellProvisioner
.
This is all you need
First off, let's create a shell script setup.sh
in the same directory and put something like this in it:
#!/bin/sh
apt-get update
apt-get install -y php5 php5-cli php-pear
hash -r
pear upgrade-all
pear install -f HTTP_Request2
What does it do?
- Update local package sources.
- Install php5, cli interpreter and PEAR installer
- reload environment
- upgrade all installed PEAR packages
- install PEAR
HTTP_Request2
When you're done editing, make sure to chmod +x
it.
Simple as that.
Putting your shell script to use
Replace your Vagrantfile
with the following:
Vagrant::Config.run do |config|
config.vm.box = "lucid64"
config.vm.provision :shell, :path => "./setup.sh"
end
Then, run vagrant up
and watch it provision. :)
Enter your virtual machine with vagrant ssh
and verify HTTP_Request2
is installed:
$ vagrant ssh [14:16:08]
Linux lucid64 2.6.32-33-server #70-Ubuntu SMP Thu Jul 7 22:28:30 UTC 2011 x86_64 GNU/Linux
Ubuntu 10.04.3 LTS
Welcome to the Ubuntu Server!
* Documentation: http://www.ubuntu.com/server/doc
Last login: Thu Jul 21 14:08:15 2011 from 10.0.2.2
vagrant@lucid64:~$ pear list -c pear
Installed packages, channel pear.php.net:
=========================================
Package Version State
Archive_Tar 1.3.10 stable
Console_Getopt 1.3.1 stable
HTTP_Request2 2.1.1 stable
Net_URL2 2.0.0 stable
PEAR 1.9.4 stable
Structures_Graph 1.0.4 stable
XML_Util 1.2.1 stable
Yay — your first steps into automation!
Fin
That's all for today — Vagrant with almost no Ruby. I hope this gets many more started!