As a developer, you've probably heard about Vagrant, Docker, Chef and other VM and container tools. This series of articles will attempt to explain what these tools do and why you may want to investigate using them. At the end I'll provide you a few scenarios of how to work with these tools to set up consistent environments.
In this first article, we'll discuss Vagrant.
Vagrant – a VM Builder
Vagrant is a tool that provisions virtual machines in a scripted way, so that the machines can be rolled out to a team of developers, or as nodes of a cluster, with ease. Vagrant works with VirtualBox, VMWare, and even Microsoft HyperV, and you can write provisioning scripts in a special file, Vagrantfile, which uses Ruby, and use any of a number of plugins to make your life easier such as Chef, Berkshelf, and Librarian.
You can use Vagrant to share configuration scripts via a centralized repository, or embed a Vagrant configuration into the source code of your project to make it easy to set up the development environment.
Vagrant uses boxes – essentially virtual machines pre-configured with software – as the starting unit of any configuration. You can find a ton of existing boxes at atlas.hashicorp.com – if one suits your needs exactly, you can use it directly. If it's close, you can create a new one based on it. You can also build your own boxes from scratch using Virtualbox.
Vagrant boxes go through two initialization stages – configuration, where the virtual machine is actually created, and provisioning, where software is installed and various network settings are applied.
The Vagrant team uses the command vagrant up to signify the starting up of a Vagrant box. Vagrant boxes are suspended or halted (a VM pause or shutdown) when you're finished using them. Finally, Vagrant boxes can be removed by using the destroy command.
You can bring in all sorts of tools to help you fetch the right software, including the extremely popular choice, Chef. Chef is another open source project that provides recipes, sets of instructions, to install software on a virtual machine. You can also install a dependency management tool, such as Berkshelf or Librarian, which allows you to create create and find cookbooks using versioning.
Vagrant – a quick start
First, download Vagrant from vagrantup.com. You'll want to make sure your machine can run typical virtual machine engines such as VirtualBox. This tutorial is geared for VirtualBox but you can also use VMWare or Microsoft Hyper-V (there is a $75 plugin to Vagrant to configure VMWare virtual machines).
Next, try the vagrant command from your OS prompt. You should get something looking like this:
$ vagrant Usage: vagrant [options] <command> [<args>] -v, --version Print the version and exit. -h, --help Print this help. Common commands: box manages boxes: installation, removal, etc. connect connect to a remotely shared Vagrant environment destroy stops and deletes all traces of the vagrant machine global-status outputs status Vagrant environments for this user halt stops the vagrant machine help shows the help for a subcommand init initializes a new Vagrant environment by creating a Vagrantfile login log in to HashiCorp's Atlas package packages a running vagrant environment into a box plugin manages plugins: install, uninstall, update, etc. provision provisions the vagrant machine push deploys code in this environment to a configured destination rdp connects to machine via RDP reload restarts vagrant machine, loads new Vagrantfile configuration resume resume a suspended vagrant machine share share your Vagrant environment with anyone in the world ssh connects to machine via SSH ssh-config outputs OpenSSH valid configuration to connect to the machine status outputs status of the vagrant machine suspend suspends the machine up starts and provisions the vagrant environment version prints current and latest Vagrant version For help on any individual command run `vagrant COMMAND -h` Additional subcommands are available, but are either more advanced or not commonly used. To see all subcommands, run the command `vagrant list-commands`.
Now you're ready to try configuring a virtual machine. Let's take a pre-fabricated machine from the organization's repository, HashiCorp, and configure an instance of it. How about Utopic Unicorn?
Downloading a Box
We can use the vagrant box command to download a box. Think of this as
a seed VM image, one that is copied when a vagrant is provisioned. These
boxes are stored in the home directory of the user under the
To show your downloaded box images:
$ vagrant box list bunchc/utopic-x64 (virtualbox, 0.2) coreos-alpha (virtualbox, 681.0.0) hashicorp/precise64 (virtualbox, 1.1.0)
To download a box:
$ vagrant box add bunchc/utopic-x64 ==> box: Loading metadata for box 'bunchc/utopic-x64' box: URL: https://atlas.hashicorp.com/bunchc/utopic-x64 This box can work with multiple providers! The providers that it can work with are listed below. Please review the list and choose the provider you will be working with. 1) virtualbox 2) vmware_desktop Enter your choice: 1 ==> box: Adding box 'bunchc/utopic-x64' (v0.2) for provider: virtualbox box: Downloading: https://atlas.hashicorp.com/bunchc/boxes/utopic-x64/versions/0.2/providers/virtualbox.box ==> box: Successfully added box 'bunchc/utopic-x64' (v0.2) for 'virtualbox'!
Setting up a Vagrant VM
Now let's set up a new Vagrant and use the bunchc/utopic-x64 image as
our base box. First, create a directory, then use the vagrant init
command to set up the Vagrantfile configuration file:
$ mkdir devbox $ cd devbox $ vagrant init --provider virtualbox 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.
Note – although you can use the vagrant box command from the previous section to pre-load a VM Box image, you don't have to. You can just start here and Vagrant will download the box anyway.
We should configure the base box for this machine, as the default is
base, a bare-bones machine with very little to offer us. Edit the
Vagrant file and change the config.vm.box line to match our fetched
config.vm.box = "bunchc/utopic-x64"
Booting our Vagrant
Now, let's boot the server:
$ vagrant up --provider virtualbox
Vagrant spins up a virtual machine using the box image – you can give it a hint if you have more than one VM engine installed – for example
vagrant up --provider virtualbox or
vagrant up --provider vmware_workstation. The default is
virtualbox if you leave the
--provider flag out of your vagrant up command.
Once the machine is up and running, you can connect to it as the vagrant user:
$ vagrant ssh
The Vagrant user you'll connect to is usually named vagrant with a password of vagrant, but that isn't actually required. In fact, Vagrant creates and signs special SSH keys between your host machine and the box, so that you don't have to enter passwords to work in the command line. Your user traditionally is granted sudo rights, so a simple su – is all you need to get in as Root.
Boxes Usually Need Provisioning
You'll only get so far with a this box. Beyond starting it, you'll want to load software. But stop… Think about what you're about to do.
If you load software by using SSH to connect and then using apt-get
directly, you'll be modifying the Vagrant instance without a way to
re-create it. Also, if you tweak settings in VirtualBox or VMWare on the
box, you'll be doing the same thing for the configuration.
How can we keep our settings and distribute them to other developers? We
do this via the Vagrantfile using the various provisioning methods.
You can automate the install of MySQL, Postgres, Apache, nginx, whatever you need to use to do your work. There are several built-in ways to provision, from directly copying and manipulating files to executing shell commands. For example, to copy a VIM editor config file into your machine you can add the following fragment to your Vagrantfile:
config.vm.provision "file", source: "./.vimrc", destination: "/etc/vimrc"
You can execute shell commands, so you can do things like:
config.vm.provision "shell", inline: "yum update"
By default, you're doing these things as the root user, so you can do any kind of long-form provisioning you want. Just remember to suppress responses from questions where you can so that the process can execute in a fully automated way.
Networking – routing to the outside
You can forward a port on the virtual machine directly to a local port on your host computer, all from your Vagrant file. For example, to forward port 80 of your box to port 8080 on the host, add:
config.vm.network "forwarded_port", guest: 80, host: 8080
Now, http://localhost:8080 will browse to a server running on the Vagrant on port 80. This sure beats the ssh -L or ssh -R commands.
There are a lot more networking features you can enable, such as host-only or bridged networking. You can read about these features and others in the Vagrant Docs.
In my next article, I'll show you how we can use the Chef provisioning tool to automate setting up software packages, and introduce you to Berkshelf, a Chef recipe management tool that can make life easier for you as you start configuring more complex Vagrants.