Between Deploys

the

Engineering Blog

Build OS Images with Ruby

Published on 03 Sep 2013 by Tom Hulihan

Packaging an application is a difficult process, often approached by piling hundreds of lines of spaghetti code on top of unsustainable assumptions. Seldom do engineers wind up with a solid, scalable system that allows others to add and replace servers with low overhead.

Recently, dotCloud revolutionized how we package applications by releasing Docker, a powerful framework to build, compose, and manage Linux images. Docker operations execute very quickly, require little memory, and operate within secure, isolated containers.

Unfortunately, scripting Docker interactions through its CLI is tedious. To write nontrivial scripts, you have to parse the output of the Docker shell commands, leading to the same spaghetti code that plagues your current packaging process. And to stay current with dotCloud's rapid release of cool new features, you have to regularly modify your scripts to work with the changing CLI.

There's no more tedium with docker-api.

$ gem install docker-api

docker-api provides a high-level interface to Docker, allowing you to package your app with Ruby. For example, package and run the Rails 4.0 app from the Rails Tutorial, from scratch, with just:

require 'docker'

image = Docker::Image.create('fromImage' => 'kaze/rubydev')
                     .run('apt-get install -y git postgresql libpq-dev nodejs rubygems libxslt-dev libxml2-dev libsqlite3-dev')
                     .run('gem install bundler')
                     .run('git clone https://github.com/railstutorial/sample_app_rails_4 /opt/app')
                     .run(['bash', '-lc', 'rvm --default use 2.0.0'])
                     .run(['bash', '-lc', 'export HOME=/root && cd /opt/app && bundle install && bundle exec rake db:migrate'])
                     .commit

container = Docker::Container.create(
  'Cmd' => ['/bin/bash', '-lc', 'export HOME=/root && cd /opt/app && RAILS_ENV=development bundle exec rails server'],
  'Image' => image.id,
  'PortSpecs' => ['3000:3000']
)

container.start

Run this code, point your browser to localhost:3000, and see the home page for the Rails Tutorial's sample app, all running inside a shiny new Docker container. Now get started at the README!

Author
Tom Hulihan