Chasing the Future: Developing Ruby on Rails from Vagrant to Docker

Owen Tran
Points San Francisco
3 min readApr 6, 2019
DISCLAIMER: This is not a HOWTO guide on running Ruby on Rails on Docker, but a brief summary of our experience attempting to “modernize” with Docker from our existing Vagrant setup.

The Points Travel rail app started back in 2012 and mostly developed on OS X (everyone loved their Macs back then — hating you butterfly keyboard). It was a struggle to deal with PostgreSQL, the correct version of ruby, compiling the gems, etc. so we standardized on Vagrant as a single command way to bootstrap the development environment and be on our merry way.

Vagrant proved trusty and most of the setup was similar to our production deployments. The only annoying issues were Mac OS upgrades, keeping the database seed files in sync, one-offs for integration testing, and the NFS volume mount. It works well once it’s all running and has been rock solid for years.

Then Docker emerged as the new hotness. In 2017, we moved from our long lived instances with Capistrano deployments to Amazon ECS with docker containers. There were a few gotchas with that endeavor with assets pre-compilation, writing out secrets.yml from ENV variables, executing scheduled rake tasks, and a few other minor things, however, it’s been a pleasure having our test and production environments encapsulated in a container with some tweaks to ENV variables.

We wanted to bring our development environment in-line with our other environments for a homogenous workflow with one Dockerfile to rule them all. We had some false starts early on with docker on Mac and networking insanity connecting to the container, but then Docker Desktop for Mac solved those issues. Also we found running Postgres.app and memcached (brew) locally reduced the complexity with the host.docker.internal hostname.

docker run -it -v /Users/owen.tran/projects/travel-rails:/travel -p 3000:3000 — rm registry.points.com/dev/travel-rails/rails/rc8.9.0:latest /bin/bash

Starting up Docker is super-quick vs. a vagrant up. Also, we could use our existing scripts with about four lines of tweaks doing away with maintaining Vagrant setup files. Excitement was in the air… we have found development nirvana!

Then we spent some time doing actual development. All the articles and posts cover setting up and running a Rails environment with Docker, but rarely do you see a discussion about what happens afterwards.

Latency, latency, latency. We’re talking an additional 400–500 ms per request, which is quite noticeable when you have a React app making multiple calls to the Rails app. The Docker team wrote a great page on the OS X filesystem and goes into depth why there are performance issues and that they are working on it. Since Feb 2016, they’ve improved it by 50x, but now the remaining improvements require significant engineering work on custom low-level components.

We tried mounting the volume with the performance tuning configurations (delegated, cached, consistent) and here were the results for running our test suite:

~20% penalty to running our test suite using the loosest consistency setting of delegated vs vagrant w/ NFS

For running the application in development, we had to disable code reload (config.cache_classes=true) to speed things up, otherwise each request required Rails to look for changes on the slower mounted filesystem. This was a deal breaker, since restarting Puma for each change isn’t a fair trade-off.

We researched the various StackOverflow comments, the Docker team’s notes, other posts and the general consensus is you will pay a tax for running Rails on Docker on a Mac. Once it was synonymous to develop Rails on a Mac, to where it’s become a liability. For those of you who have embraced Linux on your laptop already, you’re ahead of the game.

We will continue to pursue the future, but for now will stay on Vagrant and keep an eye on the Docker’s team development of OSXFS. Thanks for all the great work so far!

--

--