The problem: I need to test something or learn something new and it takes too long to get a clean machine up and running.
The problem: Well it works on MY machine. Why not yours?
On their site their tag line is "Create and configure lightweight, reporducible, and portable development environments."
On their site they show it is this easy to get started.
$ vagrant init ubuntu/trusty64 $ vagrant up
Their tutorial starts off here ; we'll use it as our guide.
Mise en Place (Everything in Place)
Before we get started let us get Vagrant and Virtualbox installed. Below I've included links to the download section of each.
Okay, lets go through some of the terms we're going t be using in this section so we are all have the same base understanding.
- Vagrantfile - The main configuration file for Vagrant. Yes the V in Vagrantfile must be capitalized.
- Provider - Vagrant can talk to many different APIs to deploy systems in various environments. Think of the term provider as what API we are talking to.
- Vagrant Boxes (Or Box) - This is a Vagrant base image. This is what helps make Vagrant so quick to deploy environments.
In this section we'll discover the basic Vagrant work flow. We'll see that regardless of provider this work flow for the most part remains the same.
Creating the Vagrantfile
Before we do anything we need to create a directory we'll use as our project directory. Each directory represents an environment.
Once we have created our project directory we can create the Vagrantfile with the vagrant init command. The command is followed by which box we want to use in this environment.
$ vagrant init ubuntu/trusty64
Note: The Vagrantfile is very well documented, but we wanted to make it less verbose we could use the --minimal option.
Bringing our Machine Up
Bringing the machine up is simple.
$ vagrant up
That's it. This command will read our Vagrantfile and bring up a machine based off the provider and the settings in our Vagrantfile.
Getting in to our Machine
One of the beautiful things about Vagrant is we do not have to worry so much about passwords and IP addresses to remember. We access our machine via the ssh sub-command.
$ vagrant ssh
Boom! Now we can get work.
And once we are done?
In the way we are going to be using Vagrant and Virtualbox we are going to be bringing up and tearing down machines often. We can tear a machine down using the destroy sub-command.
$ vagrant destroy
Note: Keep in mind all of these commands work relative to the machines in the current project directory
There are a few more one-off commands we might use within our workflow.
Checking the status of a machine.
$ vagrant status
Checking the status of ALL the machines
$ vagrant global-status
If you have made changes to your Vagrantfile and need to reload your settings.
$ vagrant reload
If you do want to bring down your machine, but do not want to completely destroy it.
$ vagrant halt
Let us see if we can do the following. For each step, how do we verify our work?
- Get Vagrant and Virtualbox installed
- Create a new Vagrant environment using ubuntu/trusty64 as your box
- Bring your machine up.
- SSH in to your machine and update all of the available packages.
Extending Our Vagrant Knowledge
Getting and Managing Additional Boxes
In previous examples we used an Ubuntu Trusty (14.04) box from Vagrant's box repository. There are two sources for additional boxes.
Atlas / Vagrant Cloud - HashiCorp Atlas ( a.k.a Vagrant Cloud)
Vagrantbox.es - Just more boxes. Can be used as secondary source. In most cases we would look to use images form Atlas
As we start to manage additional Vagrant boxes we'll want to use the vagrant box sub-commands to manage this boxes.
List out all of the Boxes
$ vagrant box list centos/7 (virtualbox, 1607.01) jhcook/centos6 (virtualbox, 188.8.131.522.3.1) rscloud (rackspace, 0) ubuntu/trusty64 (virtualbox, 20160801.0.0) ubuntu/trusty64 (virtualbox, 20160816.0.0) xenial (virtualbox, 0)
Add a new box without a vagrant init
$ vagrant box add <SOME-NAME>
Remove a box once it is no longer needed
$ vagrant box remove <SOME-NAME>
There are two ways we can access our guest VM from our host machine.
Via Port Forwarding
The following will configure the host machine to forward port 8080 to port 80 of our guest VM.
config.vm.network "forwarded_port", guest: 80, host: 8080
With this setting we can access our VM via http://127.0.0.1:8080
Via a Private Network
The following will configure an additional NIC on our guest machine. It will assign the NIC the IP address of 192.168.33.10.
config.vm.network "private_network", ip: "192.168.33.10"
With this setting we can access our VM via http://192.168.33.10
Vagrant's main purpose is to deploy an environment. It talks to the API and configures and creates VMs. The other of the environment is configuration management. Vagrant can use a number of provisioners such as Shell, Ansible, Salt Stack, Puppet and Chef.
The default Vagrantfile gives us an example of using the Shell provisioner.
config.vm.provision "shell", inline: <<-SHELL sudo apt-get update sudo apt-get install -y apache2 SHELL
The commands between <<-SHELL and SHELL will be executed on the VM.
Other provisioners can be found on Vagrant's site. https://www.vagrantup.com/docs/provisioning/
If at first we don't succeed . . . . Vagrant allows us to iteratively re-run just the provisioning section of our Vagrantfile.
$ vagrant provision
Up until this point we have only been working with a single machine. Part of the power of Vagrant is we can deploy and configure entire environments.
The following is an example of creating a Vagrantfile with multiple machines.
Example Vagrantfile for multiple machines
This file configures two machines with the hostnames of server and client.
Vagrant.configure(2) do |config| config.vm.define "server" do |server| server.vm.box = "ubuntu/trusty64" server.vm.hostname = "master" server.vm.network "private_network", ip: "192.168.33.100" server.vm.provider "virtualbox" do |vb| vb.gui = false vb.memory = "1024" end end config.vm.define "client" do |client| client.vm.box = "ubuntu/trusty64" client.vm.hostname = "slave" client.vm.network "private_network", ip: "192.168.33.200" client.vm.provider "virtualbox" do |vb| vb.gui = false vb.memory = "1024" end end end
With multiple machines we bring up and access them in a slightly different way.
Interacting with the Machines
Bring up the entire environment
$ vagrant up
Note: the following examples
$ vagrant up <SERVER-NAME>
Connecting to a single machine
$ vagrant ssh <SERVER-NAME>
Destroying a single server
$ vagrant destroy <SERVER-NAME>
Hands On - Extended Vagrant
Let us see if we can do the following. Use this as a template and expand to try out new ideas.
Keep in mind to think about how you would verify each step of your work.
- Create a new project directory
- Create a multi-machine Vagrant file
- The machine should be two different operating systems
- Machine 1 - 192.168.33.100
- Machine 2 - 192.168.33.200
- Configure the shell provisioner to do the following
- Server 1
- Configure Apache, PHP, Wordpress
- Server 2
- Configure MySQL
- Server 1
- Share your Vagrantfile with somebody else and see if they can bring up the same environment.
Here is mine.
# Example Vagrantfile for multiple machines # This file configures two machines with the hostnames of server and client. Vagrant.configure(2) do |config| config.vm.define "server" do |server| server.vm.box = "centos/6" server.vm.hostname = "cent6" server.vm.network "private_network", ip: "192.168.33.100" server.vm.synced_folder "./", "/var/www/html" server.vm.provision "shell", inline: <<-SHELL sudo yum update sudo yum install -y httpd php php-mysql SHELL server.vm.provider "virtualbox" do |vb| vb.gui = false vb.memory = "1024" end end config.vm.define "client" do |client| client.vm.box = "centos/7" client.vm.hostname = "cent7" client.vm.network "private_network", ip: "192.168.33.200" client.vm.provider "virtualbox" do |vb| vb.gui = false vb.memory = "1024" end client.vm.provision "shell", inline: <<-SHELL sudo yum update sudo yum install -y mariadb-server SHELL end end
YAY! You made it!
Thank you for taking the time to go through this quick-start tutorial.