I started using Vagrant for local development when I realized it was a waste of time configuring my code to be able to run on Mac. At the time I was beginning to build a continuous delivery pipeline in the AWS cloud. The CI servers I needed were going to run in a Linux-based environment and although most of the code was in Python, which lets you isolate things with virtual environments, there still is a need to interface with the operating system. Jumping through hoops on a Mac to get a few Python libraries to build successfully wasn’t always fun. Even less fun was navigating those same hoops once again because the system the code that now runs perfectly on a Mac, is a sea of red on Linux. At some point I figured it out. Who cares if the application runs on OSx? It is not a Mac app.

Enter Vagrant. What won me over was the command line integration. The ability to fire up a virtual machine with a command and then ssh into it as if it were in the cloud. Vagrant allowed me to work in Linux with all the benefits of a Mac desktop environment. So I changed my development work-flow, making a few tweaks to accommodate the guest OS.

The first thing I did was move the source code in my working directory to ~/vagrant on my host machine. This is the directory where I put my Vagrantfile. Since Vagrant automatically maps the Vagrantfile directory on the host machine to the /vagrant directory in the guest machine, I could just sync my repos to this folder as well.

At the time I was using PyCharm a lot. I pulled directories into my PyCharm workspace from this shared directory. Then I was able to run the code in a Linux context, but modify it in PyCharm, taking advantage of some of the quick navigation features that an IDE like PyCharm can offer – things like clicking into a method to see its implementation.

There are some drawbacks to using Vagrant though. A vagrant instance derives its hard drive size from a base “box” that someone has to set up manually and then publish to a vagrant box repository. The boxes I have used are limited to 10 GB in size, which has created a need to be mindful of where files are landing when doing things like building up virtual environments. I’ve found the key is to target the synced /vagrant folder as much as possible.

Most of my pain as far as dealing with the size of the Vagrant instance has come from Docker. I haven’t had much success getting Docker to use the host file system when running from the Vagrant guest. I’ve heard that Docker works much better now on OSx than it did before and perhaps it’s more straightforward to use however I focused on developing a work-flow that minimizes the amount of docker containers I need to run at once. Actually it’s a work-flow that minimizes the amount of state I need to maintain at any given time. Whether in a container or on a development machine, my goal is to be able to spin up and destroy any component needed for development anytime.

Another drawback from someone who writes automated tests and testing frameworks is that it’s a little more straightforward to just use the host system to fire up tests that involve the browser. Browsers can be launched from a Vagrant guest, but I’ve found that working with the host machine just makes it easier when trying to get selenium tests up and running. However, once you’re ready to run those tests headless, give Vagrant, or better yet Docker inside of Vagrant.