We removed our free Sandbox April 25th.
You can read more on our blog.

Thin

Thin is a Ruby web server that glues together the Mongrel parser, the Event Machine I/O library, and the Rack interface. According to Thin webpage, this makes it “with all humility, the most secure, stable, fast and extensible Ruby web server bundled in an easy to use gem for your own pleasure”.

This tutorial will show how to use Thin instead of the default nginx + Passenger stack offered by dotCloud.

All the code presented here is also available on GitHub, at http://github.com/jpetazzo/thin-on-dotcloud.

dotCloud Build File

The dotCloud Build File, dotcloud.yml, describes our stack.

We declare a single “Ruby-Worker” service. We use a “Ruby-Worker” because it features two useful things for us:

  • a Ruby interpreter (obviously!)
  • a mechanism to install gems

The role and syntax of the dotCloud Build File is explained in further detail in the documentation, at http://docs.dotcloud.com/guides/build-file/.

# dotcloud.yml

www:
  type: ruby-worker

Gemfile & Dependencies

To tell dotCloud to automatically install the gem for Thin, we create a standard Gemfile. dotCloud will detect this, and automatically use bundler to install dependencies defined in the Gemfile.

See http://gembundler.com/gemfile.html for details about bundler and the Gemfile format.

# Gemfile

source 'http://rubygems.org'
gem "sinatra"
gem "thin"

Rack config file

Thin can load a Rack config file. We’ll use this start our Sinatra application.

# config.ru

require './stream_demo'
run Sinatra::Application

Ruby Code

We now need an application that will respond to the http requests. We create a ruby script that defines three endpoints /, /publish, and /subscribe.

# stream_demo.rb

require 'sinatra'

conns = []

get '/' do
  erb :index
end

get '/subscribe' do
  content_type 'text/event-stream'
  stream(:keep_open) do |out|
    conns << out
    out.callback { conns.delete(out) }
    out << "event: init\n\n"
    out << "data: there are now #{conns.length} stream(s).\n\n"
  end
end

get '/publish' do
  conns.each do |out|
    out << "event: publish\n\n"
    out << "data: hello #{out}!\n\n"
  end
  "published to #{conns.length} stream(s).\n"
end

__END__

@@ index
  <article id="log"></article>

  <script>
    var source = new EventSource('/subscribe');

    source.addEventListener('message', function (event) {
      log.innerText += '\n' + event.data;
    }, false);
  </script>

Route Requests to Thin

By default, “Ruby-Workers” don’t have an http route. We’ll need to expand the dotcloud.yml file to add a http endpoint and to connect that endpoint to the running process.

# dotcloud.yml

www:
  type: ruby-worker
  ports:
    www: http
  processes:
    thin: thin -p $PORT_WWW start

Now we can push our application with dotcloud push and browse our service URL.