< go back to home

Introduction To Vagrant Basics

June 25, 2017

Vagrant is an awesome virtualization tool. That means that with it, you can run and manage different operating systems in your local machine. I find this useful in the following use cases:

I'm sure there are still other use cases I failed to mention but those 4 are the ones I find everyday use for Vagrant. I hope those get you excited or at the very least interested in Vagrant :) Let's go and start setting up Vagrant.

First thing to do is to install Virtualbox which is a virtualization software that is required by Vagrant. This is important as Virtualbox is where the actual virtualization happens. Vagrant helps manage virtual environments to easily achive the four use cases I described. The installation guideline for Virtualbox can be found here. For Ubuntu users, a more straight forward guide is found here.

If the installation was succesful, "Oracle VM Virtualbox" should open with this window:

Next is installing Vagrant itself. The download documentation can be found here. If you are using Ubuntu, you can just run the command "sudo apt-get install vagrant". But that would install 1.8 version only, if you want to run the latest version, refer to this post.

Check vagrant version and verify that it works:

$ vagrant --version
Vagrant 1.9.1

Let us construct a scenario to show Vagrant on actual use cases to better appreciate and understand it. Let's say we want to have an ExpressJS web application running in a virtual OS Centos 7 as our development environment. Let us start by fetching a Vagrant Box. Boxes are base images of OS that will be used for virtualizations. This might take a while as it downloads the whole image of an OS but it will only be used once as it can be shared for different projects. For our purpose, we will use Box named "centos/7". You can search for different boxes in the Vagrant website.

$ vagrant box add centos/7

Create a folder that will serve as root project and enter there. Initialize the project folder to have a Vagrant setup through "vagrant init" command that will generate a configuration file for vagrant.

$ mkdir mywebsite
$ cd mywebsite

# Initialize a Vagrant file. This will generate a "Vagrantfile"
$ vagrant init centos/7
$ ls
Vagrantfile

After the Vagrant initialization, we will start the vagrant environment. If "centos/7" box is not yet present, it will first download it but since we've already did that in the "vagrant box add" command, it will just start the virtual environment.

$ vagrant up

If the startup is succesful, we'll enter the virtual OS through SSH:

$ vagrant ssh
[vagrant@localhost ~]$

Notice that the bash prompt is now different with user "vagrant". This means you are now in the virtual OS. Run "cat /etc/redhat-release" to verify. Everything you install here will not propagate to your host machine except for the file changes that we will get into later. So for now, let us install NodeJS in our virtual environment. The installation is based on this guide.

# Install NVM
[vagrant@localhost ~]$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash
[vagrant@localhost ~]$ source ~/.nvm/nvm.sh

# Install NodeJS V8
[vagrant@localhost ~]$ nvm install 8
[vagrant@localhost ~]$ nvm use 8
[vagrant@localhost ~]$ node --version
v8.1.2
# Install Express Generator
[vagrant@localhost ~]$ npm install express-generator -g

# Generate website codebase
[vagrant@localhost ~]$ express website
[vagrant@localhost ~]$ cd website
[vagrant@localhost ~]$ npm install

# Run webserver
[vagrant@localhost ~]$ node bin/www &

# Check website
[vagrant@localhost ~]$ curl localhost:3000

If the setup is succesful, you should see the html content in the last command. You've succesfully setup a Node webserver inside the virtual machine without having to affect your host machine. Good job! But it's not yet done. There are now two challenges that we have to work on:

Those can be accomplished by tweaking the configurations in Vagrantfile. To know more about Vagrant configurations, refer to the their documentation. We'll just tackle the basics for this article. Open Vagrantfile and edit it simillar to the code below:

Vagrant.configure("2") do |config|
config.vm.box = "centos/7"

  # Host folder "./" which is the current project folder
  # is synced to "~/Code" folder in the VM.
  config.vm.synced_folder "./", "/home/vagrant/Code"

  # VM port 3000 will be mapped to 3001 of host machine.
  # That means you may access the website to "http://localhost:3001" in
  # the browser.
  config.vm.network :forwarded_port, guest: 3000, host: 3001
end

As noted in the comments, syncing of folder is handled in the "config.vm.synced_folder" line while being able to access VM network is accomplished through config.vm.network. Exit VM through "exit" command and reload Vagrant.

$ vagrant destroy
y
$ vagrant up
$ vagrant ssh

After re-entering Vagrant, check "~/Code" folder. That will be the folder that is in-sync between the host and the guest machine. Whatever files we add, edit or delete within that folder will be reflected both ways to host and guest. So let us redo the NodeJS setup and website project there.

* Note: "host machine" refers to the actual OS environment and hardware of your computer while "guest machine" is the virtual OS running in your computer.

# Install NVM
[vagrant@localhost ~]$ cd ~/Code
[vagrant@localhost Code]$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash
[vagrant@localhost Code]$ source ~/.nvm/nvm.sh

# Install NodeJS V8
[vagrant@localhost Code]$ nvm install 8
[vagrant@localhost Code]$ nvm use 8
[vagrant@localhost Code]$ node --version
v8.1.2

# Install Express Generator
[vagrant@localhost Code]$ npm install express-generator -g

# Generate website codebase
[vagrant@localhost Code]$ express website
[vagrant@localhost Code]$ cd website
[vagrant@localhost Code]$ npm install

# Run webserver
[vagrant@localhost Code]$ node bin/www &

You should be able to see the running website now in your browser through "http://localhost:3001". You'll also notice that the "website" folder is now present in our host project folder even though we generated it in the VM. As mentioned, changes in files within the project folder is synced two-way.

We might be tempted to declare that this is done but as you might have realized, there is actually a third challenge that we need to handle. That is with regards to the repetition of setting up whenever we restart Vagrant. For that we will use "provisioning". There are a lot of specialise tools for provisioning like Chef and Ansible, but for this, we'll use plain old Bash.

Create a provision file named "provision.sh" in the project folder. It will contain the instructions on setting up our environment using bash script. It will be basically just the commands we've run on the previous step. For more information about provisioning, refer to Vagrant's documentation.

$ touch provision.sh

Populate the file with the following bash codes:

cd ~/Code
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash
source ~/.nvm/nvm.sh

# Install NodeJS V8
nvm install 8
nvm use 8
node --version

# Install Express Generator
npm install express-generator -g

# Generate website codebase
express website
cd website
npm install

# Run webserver
node bin/www &

Update Vagrantfile by adding line `config.vm.provision "shell", path: "provision.sh" before the "end" keyword.


Vagrant.configure("2") do |config|
  config.vm.box = "centos/7"

  config.vm.synced_folder "./", "/home/vagrant/Code"

  config.vm.network :forwarded_port, guest: 3000, host: 3001

  #insert provisioning declaration here
  config.vm.provision "shell", path: "provision.sh"
end

Reload Vagrant now. This time, you don't have to manually setup the environment. After "vagrant up", you should be able to go directly to "http://localhost:3001" in the browser and see the website.

$ vagrant destroy
y
$ vagrant up

That's it. You now have a Vagrant setup that is capable of building itself and syncing files and networks. Happy coding!!! :)




< go back to home