Vagrant is a tool by HashiCorp that is used for creating lightweight development environments. As someone that likes to experiment with all the languages, it can often be a massive pain to get a local dev environment set up before jumping into a new project.
There have been times where I go back to a language, only to find that the SDK or runtime that I installed previously is out of date, so I have to uninstall it before reinstalling the correct version. This is a lot of effort to go to if I only end up spending maybe a weekend building a basic prototype.
Thankfully, tools like Vagrant exist to make this process much easier. By containing your projects and installations within a tiny virtual machine, your changes only last as long as the virtual machine exists, and they don't pollute the host machine with unused runtimes and SDKs.
Perhaps my favourite thing about Vagrant is its ability to define a complete development environment within a single, human-readable file. This file can be kept in the project's repository so any time you need to do further work, you can simply spin up the dev environment and get to work.
Installation
Installing HashiCorp is as simple as going to the HashiCorp website and downloding the appropriate installation client.
If you happen to be using Windows, Vagrant will not work if you have Hyper-V enabled, so you'll need to disable this before continuing. You can do this from an administrator PowerShell prompt with:
Disable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-All
Creating a Vagrant environment
In order to create a Vagrant environment, we must first choose a box to base our environment on. A box in Vagrant represents a base image for a virtual machine, usually defining the underlying operating system and potentially installed runtimes.
Boxes can be found on the Vagrant Cloud, or alternatively created by us. To keep things simple, lets create an instance of the hashicorp/bionic64 box from the Vagrant Cloud. To do this, open a terminal and enter vagrant init hashicorp/bionic64
. This should create a Vagrantfile
in your directory contining the following:
# Comments removed for readability
Vagrant.configure("2") do |config|
config.vm.box = "hashicorp/bionic64"
end
From here, we can simply enter vagrant up
in the terminal to create an environment based on our Vagrantfile. A quick vagrant status
will allow us to see if our environment is running:
$ vagrant status
Current machine states:
default running (virtualbox)
The VM is running. To stop this VM, you can run `vagrant halt` to
shut it down forcefully, or you can run `vagrant suspend` to simply
suspend the virtual machine. In either case, to restart it again,
simply run `vagrant up`.
From here, we can connect to the environment by entering vagrant ssh
in the terminal. We don't need to do this right now, but go ahead and give it a try if you're curious.
Configuring our environment
Okay, so lets say we want our Vagrant environment for building a new Flask application with Python. We have three dependencies for our environment: python, pip and flask.
Installing our dependencies
Luckily, python 3 comes installed as standard in Ubuntu 18.04, so all we need to install at this point is pip3. In Vagrant, you can use something called a provisioner, which is a fancy term for a post-creation script runner. Add the following to your Vagrantfile:
config.vm.provision "shell", inline: <<-SHELL
sudo apt-get update
sudo apt-get install -y python3-pip
pip3 install flask
SHELL
Tear down your current environment using vagrant destroy
and recreate it using vagrant up
. You'll notice that provisioning our environment now takes a little longer, which is due to the provisioner running our script above.
Our Application
In the same directory as your Vagrantfile, create a new file called app.py
, and paste in the following code:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello from Vagrant!'
In order to access this service via the browser, we need to forward port 5000 on the Vagrant machine to a port on our host machine. I'll keep them both at 5000 just to keep it simple. Add the following to your Vagrantfile just above your provisioner:
config.vm.network "forwarded_port", guest: 5000, host: 5000
After this, we need to do a vagrant reload
to rebuild our environment from the new Vagrantfile. This will save us a lot of time as it will only update the things that have actually changed and won't have to run the provisioner again.
Synced Folders
You'll notice that I'm referencing a directory called /vagrant
above, and I think this is a good time to explain Synced Folders in Vagrant. A synced folder is a directory that is shared between your host machine and your virtual machine, allowing you to work on your project files on your own machine but compile or run your application within the Vagrant environment. There is a synced folder set up by default in a Vagrant environment, and it is set to directory that your Vagrantfile is located in.
Give it a try: vagrant ssh
into your environment and navigate to your /vagrant
directory. If you list the items in that directory, you'll see your Vagrantfile
and app.py
.
Running the application
Okay, so we're ready to actually run the Flask application, so ssh into your machine and enter the following into the terminal:
Flask requires the FLASK_APP
environment variable to be set in order to for the _flask run
_command to work.
$ export FLASK_APP=/vagrant/app.py
$ flask run --host=0.0.0.0
The application should now be running on http://localhost:5000, and going to that url on your host machine should yield the message Hello from Vagrant!
. Now we have a fully featured dev environment, we can include the Vagrantfile in our project repository so any other developers working on the project can simply spin up the exact same environment for themselves!
If you've made it this far, you probably now know as much about Vagrant as I do, and I hope you love it equally too. If you have any further questions or comments, please do not hesitate to comment or even give me a follow if you like my work.
Top comments (0)