Developing for Linux on a Mac with Vagrant
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.
For other items related to DevOps and test automation visit my blog at local-droid.com
Nice write up of your experience