Setting up development environments is a nightmare to most of web developers. But what can we do? It’s a part of our work. We need different setups and tools for different projects, we also need separate environments for development, testing, etc. Usually, it ends up with a big mess - bunch of web servers, DB servers, message brokers and other stuff running on your computer. Things can get even worse when working in teams. Sounds familiar? What if it would be possible to have isolated, portable environments which could be set up within several terminal commands? Actually, it is easily achievable with Vagrant and Chef. In this tutorial we will cover setting up a virtual environment running Node, MongoDB and Express framework on it using Vagrant and Chef.
Vagrant is software for creating and configuring lightweight, reproducible, and portable virtual development environments.
First of all, you will need to install VirtualBox and Vagrant itself. The installation packages and instructions could be found accordingly:
When Vagrant is in place, you can start exploring it by running the following commands from your terminal:
$ vagrant init ubuntu/trusty64 $ vagrant up
Congrats! You’ve just created a virtual machine running vanilla Ubuntu 14.04 (64-bit). You can now SSH to it using the following command:
$ vagrant ssh. It’s so easy, isn’t it? In fact, you can find loads of ready to use virtual boxes containing popular stacks (LAMP, MEAN, etc.) - visit VagrantCloud and browse them. Let’s say, you would like to start a virtual machine containing LAMP stack. In that case, you can use scotch/box box by running the following commands:
$ vagrant init scotch/box $ vagrant up
Everything looks great, but what if I need more flexibility and configuration capabilities? – you may ask. Luckily, there is Chef (we are going to use Chef-solo in this tutorial). It allows us to install, configure and manage packages on Vagrant virtual machines without complicating configuration. There are more than 2000 packages (so called cookbooks) on Chef market so you’ll probably find everything you need for your development environment.
Vagrant + Chef-solo
Step 1. Create a vagrant file
Go to the destination folder (for virtual machine) and create a Vagrantfile with the content provided below. Vagrantfile is used to describe the type of machine and to provide ‘instructions’ how to configure this machine. Please check the comments in the Vagrantfile – they should be self-explanatory enough to get an understanding what’s happening there.
# -*- mode: ruby -*- # vi: set ft=ruby : # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| # All Vagrant configuration is done here # Every Vagrant virtual environment requires a box to build off of. config.vm.box = "ubuntu/trusty64" config.ssh.forward_agent = true config.vm.network "private_network", ip: "10.3.3.3" # Forward ports for MongoDB and Express app config.vm.network "forwarded_port", guest: 27017, host: 27017, auto_correct: true config.vm.network "forwarded_port", guest: 3000, host: 3000, auto_correct: true config.vm.provision :shell, :inline => "sudo apt-get update -y" config.vm.provision :shell, :inline => "sudo apt-get install curl -y" config.vm.provision :shell, :inline => "curl -L https://www.opscode.com/chef/install.sh | sudo bash" config.vm.provision :chef_solo do |chef| # Paths to your cookbooks (on the host) chef.cookbooks_path = ["cookbooks"] # Add chef recipes chef.add_recipe 'nodejs' chef.add_recipe 'mongodb::default' chef.add_recipe 'git' # Is required for NPM end # Install express and express-generator packages globally config.vm.provision :shell, :inline => "npm install -g express express-generator" # Share an additional folder to the guest VM. The first argument is # the path on the host to the actual folder. The second argument is # the path on the guest to mount the folder. And the optional third # argument is a set of non-required options. # config.vm.synced_folder "../CHANGE_TO_YOUR_PATH", "/MyApp" end
Step 2. Download Chef packages (Cookbooks)
Before we can proceed with the creation of virtual machine, we need to download Chef packages and store them locally on the ‘cookbooks’ folder (within our destination folder). I’m using Librarian to automate this task. Please check their github page for installation instructions. After Librarian is installed, we can create a Cheffile (within our destination folder) containing the packages that should be downloaded:
# encoding: utf-8 site 'http://community.opscode.com/api/v1' cookbook "nodejs" cookbook "mongodb" cookbook "git"
In order to download the packages run the following command:
$ librarian-chef install --verbose. This may take some time to download them.
Step 3. Run your virtual machine
Perfect! We are almost there. In order to start the virtual machine cd to the destination folder, run
$ vagrant up and go to get a cup of coffee as this will take some time to download and setup your virtual machine.
Once our virtual machine is up and running we can now perform a small test with it. SSH to virtual machine using
$ vagrant ssh and run the following commands:
$ express MyApp $ cd MyApp && npm install $ DEBUG=MyApp:* ./bin/www
These will create and run a new Express app on your virtual machine. Open your browser (in host) and navigate to http://10.3.3.3:3000 – you should see the starting page of your Express app. That’s it, now you have a new development environment up and running!
In this tutorial we’ve learned the basics of using Vagrant+Chef. Now you are ready to start setting up your own reproducible & portable virtual environments with a custom stack on them. This tutorial is just an intro - these tools are much more powerful! Please check their documentation.
What’s next? Your next step could be getting familiar with ‘Synced Folders’ which is really useful when working with virtual environments. Go to Vagrant documentation and check the very last lines of the Vagrantfile to get started with it.
I hope you’ll find this tutorial useful and it will help to save your time and efforts in the future. Good luck and happy coding!