One of the things I love about Vagrant is how it allows you to quickly create a VM that is very close to your production environment (or better yet EXACTLY like it). We’re starting to work on scaling STAGES from a single server to multiple servers so I’m using Vagrant as the test bed for this process. Because of this we need to work with multiple VMs in the same Vagrant file which isn’t covered by most tutorials.
The Base Config
I’m going to use the basic configuration we created in Getting Started With Vagrant stripped down to the very basics:
Then to make sure everything is working correctly:
If you’ve worked with Vagrant before you’ve seen this a MILLION times but I want to draw your attention to the “default” text that shows up over and over again.
If we don’t destroy this box before we do the next step we’ll leave it running and taking up disk space so we’re going to destroy it:
Again notice “default”.
And Then There Were Two
Vagrant allows us to define more virtual machines by wrapping them in blocks like the following:
You absolutely need to make sure you give them a unique hostname, IP address, and name setting so there aren’t conflicts. Otherwise it won’t work. At Zimco we have a Google Doc spreadsheet that keeps track of all our Vagrantfile VMs so we don’t need to worry about conflicts (that way we can have multiple projects running at the same time in case we need to jump over and fix a quick bug or eight).
For our example our initial (see below for the final) Vagrantfile looks like this:
This Vagrant file specifies two different VMs. One is the “web” VM and it provides web services (duh) and the other is db and it provides database services (duh again).
Now when we run vagrant up we see some very different results:
The first thing to point out here is that “default” text is gone and in it’s place is the “web” and “db” names that we defined in the Vagrantfile above. The second is that we were able to create two VMs with just a single command. I remember a couple years ago when it took hours to manually creating the VMs in VirtualBox and install Linux (sigh).
The cool thing is that vagrant automatically runs most commands on all of the VMs in the Vagrantfile:
But you can also run commands on a single VM by adding the name of the VM after the command:
There are a few commands that will require you to enter the VMs name but Vagrant is helpful enough to tell you when that happens:
To get around this limitation (I SSH into my web server WAY more than my DB server) you can specify a default VM when you define the virtual machine:
Then the above command will work:
Preventing some machines from booting
Let’s say you’re testing a setup with multiple web servers.
90% of the time you don’t actually need to test the load balancing piece and can run just a single web server. Normally, if you ran vagrant up it would boot all of the VMs every time so you’ll need to run vagrant up for every VM that you want to have running:
This can be tedious but thankfully Vagrant has a setting that will allow you to keep VMs from auto starting:
Then you can just run vagrant up and it will only boot those VMs that don’t have autostart: false:
Fixing the SSH Forwarding Issue
Note: I’m guessing this section only affects a VERY small number of setups but it’s here in case you (like me) need it.
For brevity I removed a lot of the output from when we did the vagrant up to the two VMs above. In doing so I removed a potential problem. Vagrant automatically forwards port 2222 on the host to port 22 on the VM (unless there’s a conflict). This is helpful because then you can SSH into the machine from another computer (as I do) in order to do searches and check services.
Bringing back the pieces that are important.
From this output we see that when we brought up the web VM it automatically took port 2222 on the host computer for the SSH forward and db took port 2200. That’s fine for most people but what if you have multiple projects running on a single host computer? Because Vagrant automatically picks the ports it’s possible they won’t match in the future.
For example what happens if we bring up db and then web:
Now we have opposite port assignment. If you’re like me and need these ports to always be the same (so you can consistently connect to them and don’t have to worry about looking it up every time) this is an annoyance.
To fix this we’re going to add an explicit port forward to the configuration with an id of “ssh”. This also fixes this error message that you might see:
When I forward ports I try to stick to the last octet concatenated with the port number so for our VM we’re forwarding port 22 and the IP address is 192.168.56.101 so the host port will be ‘101’ + ‘22’ = ‘10122’.
Here’s our final Vagrantfile:
And to check it works:
Now we just need to get the correct software installed and we’ll be on our way.
Have a question ask it in the comments?
Scott Keck-Warren
Scott is the Director of Technology at WeCare Connect where he strives to provide solutions for his customers needs. He's the father of two and can be found most weekends working on projects around the house with his loving partner.
Like this post? Don't forget to follow us on Twitter and Facebook for updates.