Discussion: Thoughts on virtualization

Just curious to know what my fellow developers feel on using some sort of visualization for development environments. Recently I’ve been getting into Vagrant. Just wanted to know if anyone else is using vagrant or similar to setup their local development environments. I love to hear what other peoples workflow setups are like! :smile:

-Silas

Seems to be getting more and more common these days, but as far as I know, no one at thoughtbot has made the jump. We all develop locally. Just one data point!

I’ve been using Vagrant for most development since before I joined thoughtbot, so I’m one of the few here who doesn’t develop locally. As with any technology there are pros and cons to balance against each other.

For Vagrant

  • Automated setup makes it easier to get up and running on an established project. I’ve especially seen benefits for designers in some (pre-thoughtbot) projects, where setting up a complex environment became as easy as typing vagrant up.
  • Isolated environments make it easier to change things. Each project runs on a different machine, so I only ever have to think about the needs of the project I’m currently working on. If I need to upgrade Postgres, or to erase all of my Redis data, or to install MongoDB, I don’t have to think about implications for the project I’ll be working on tomorrow, or spend time fixing it if I did break something. Each project’s environment will stay exactly as I leave it.
  • The development environment can be closer to production. I’ve run into issues before where different versions of database servers have caused issues that weren’t seen until production, with virtualisation it’s easier to run the same version of everything in both environments.
  • VM configuration is runnable documentation. A Vagrantfile, and the associated chef/puppet configuration or set up scripts are a good way to document the project’s dependencies (beyond what can be listed in a Gemfile), for example the capybara-webkit vagrant_setup.sh lists all of the packages needed to get a brand new Ubuntu install ready for capybara-webkit development work.

Against Vagrant

  • Setting up new machines takes time. Even starting from a good base box, there’s usually some project specific set up to do. Doing this properly – so that it’s automated for future developers – takes more time than just quickly installing a package.
  • Virtual machines are slower. When developing on a VM you don’t have your machine’s full resources available to you. On a modern MacBook Pro I don’t notice, but on older machines some operations were noticeably slower.
  • Shared file system are complicated. When developing on a VM you’re using a shared file system which has some quirks, especially when you use the default Virtual Box sharing setup. I’ve found some tools need extra work to get them working in this environment, for example Spring needs some configuration to run on Virtual Box, and I never figured out how to get Zeus working properly.
  • You have to think about two machines. My machine has my git and vim configuration, but the virtual machine has the dependencies needed to run my project’s tests. I have to make sure that I run the right commands on the right machine. After a couple of years of virtualised development I’m very used to this split and I have my tools set up for it, but it did take some adjustment.

Since we’re heavy vim users, a development environment in the cloud makes
plenty of sense as a way to get rapid (and, importantly, asynchronous) feedback
from teammates on the product before the code.

While the primary benefit of a Development Platform as a Service is faster
product cycles, it has a few side benefits, too:

  • Better parity between development, test, staging, and production.
  • Ease the burden of setting up a laptop for development.
  • Eliminate some differences in development environments (OS X vs. Linux, RVM
    vs. rbenv, etc.), which are the source of bugs and lost debugging time.
  • Facilitate easy pair programming.
  • Piggyback on GitHub’s access control to the source code.
  • Develop on Chromebooks.
  • Pipe production traffic to development using em-proxy to debug performance.

Nitrous.io is the best Development Platform as a Service that we’ve found
so far. While still in alpha, we’ve noticed benefits such as:

  • Simple to get started.
  • Ubuntu machine seemed crazy fast.
  • Our one roadblock was answered within 30 minutes by the founder in a chat room.

A few things needed work:

  • They were a patch level behind on Ruby 1.9.3.
  • Their tmux version was behind.
  • Since their boxes don’t provide admin access, it didn’t seem possible to
    upgrade tmux via sudo apt-get.
  • It didn’t look like their “box templates” are open source.

Nitrous features an IDE that we don’t care about ourselves (we would always use
vim via SSH). However, the IDE could be a nice environment for teaching new
programmers like we used to on Heroku Garden.

The primary downside of a service like this is that it requires an internet
connection. 99% of the time, that shouldn’t matter. Read a book on those
cross-country flights!

Moving the development environment to the cloud presents an opportunity to
examine how external services should be set up differently to offload work done
by the development platform and to better match staging and production.

The most important external service is the SQL database. On Nitrous, we’re
experimenting with using Heroku Postgres. One potential benefit might be fast
production-to-development backups with PG Backups.

It seems like having a default config/database.yml like the following could be
a nice separation of configuration and code:

development: &default
  adapter: postgresql
  database: <%= ENV['DEVELOPMENT_DATABASE_ID'] %>
  host: <%= ENV['DEVELOPMENT_DATABASE_HOST'] %>
  min_messages: WARNING
  password: <%= ENV['DEVELOPMENT_DATABASE_PASSWORD'] %>
  port: <%= ENV['DEVELOPMENT_DATABASE_PORT'] %>
  username: <%= ENV['DEVELOPMENT_DATABASE_USER'] %>

test: &test
  <<: *default
  database: <%= ENV['TEST_DATABASE_ID'] %>
  host: <%= ENV['TEST_DATABASE_HOST'] %>
  password: <%= ENV['TEST_DATABASE_PASSWORD'] %>
  port: <%= ENV['TEST_DATABASE_PORT'] %>
  username: <%= ENV['TEST_DATABASE_USER'] %>

I saw this in the newsletter :wink: