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

Ruby

The ruby service can host any Ruby web application compatible with the Rack standard.

That includes modern Ruby web frameworks such as Rails and Sinatra.

Basic Use

Let’s assume that you are building a DotCloud application called “ramen”. For the sake of simplicity, we will also assume that everything related to this application is located in a directory called “ramen-on-dotcloud”.

Let’s setup our environment:

$ dotcloud create ramen
Created application "ramen" using the flavor "sandbox" (Use for development, free and unlimited apps. DO NOT use for production.)
$ mkdir ramen-on-dotcloud

A DotCloud application is described by a Build Files, which is a simple YAML file named “dotcloud.yml” located in our “ramen-on-dotcloud” directory. To add a new service to our app, we just add the following lines to “ramen-on-dotcloud/dotcloud.yml”:

www:
  type: ruby
  approot: helloruby

This Build File instructs the platform to use the code in the directory “helloruby” and do whatever is necessary to expose the Rails or Rack app contained therein.

Let’s create a very minimal Rack application for demonstration purposes:

$ mkdir ramen-on-dotcloud/helloruby

We also need the following directories; otherwise, the web server won’t recognize your app as being valid:

$ mkdir ramen-on-dotcloud/helloruby/public
$ mkdir ramen-on-dotcloud/helloruby/tmp

Now, we just need to add a file called config.ru into the helloruby directory, containing the following code:

app = Proc.new do |env|
    [ 200, {'Content-Type' => 'text/plain'},
      env.each.map {|k,v| "#{k}=#{v}\n"}.collect ]
end
run app

This will dump the whole environment of the request in the simplest possible format.

We can now push our application to DotCloud:

$ dotcloud push ramen ramen-on-dotcloud/
# upload /home/.../ramen-on-dotcloud/ ssh://dotcloud@uploader.dotcloud.com:21122/ramen
# rsync
[...]
sent 8.11K bytes  received 352 bytes  995.06 bytes/sec
total size is 14.78K  speedup is 1.75
Deployment for "ramen" triggered. Will be available in a few seconds.
2011-06-28 04:27:34 [api] Waiting for the build. (It may take a few minutes)
2011-06-28 04:27:48 [www.0] service booted
2011-06-28 04:27:48 [www.0] The build started
2011-06-28 04:27:48 [www.0] Fetched code revision rsync-1309235251.44
2011-06-28 04:27:51 [www.0] Reloading nginx configuration: nginx.
2011-06-28 04:27:51 [www.0] The build finished successfully
2011-06-28 04:27:51 [api] Deploy finished

Deployment finished successfully. Your application is available at the following URLs
www: http://ramen-dotcloud.dotcloud.com/

URLs have been generated for each web service in your application from your application an account names. Open your browser to see your new service in action!

If you want to attach a better URL to your application, read the Custom Domains documentation.

Internals

DotCloud ruby uses Nginx as the HTTP frontend. The passenger module is used to mount Rack-compliant applications.

To support switching between different versions of Ruby, as well as custom gems installation, we use RVM and bundler.

Adapting Your Application

The ruby service relies on standard tools and best practices to build and deploy your app. That means that adapting your code to run on dotCloud will require minimal effort (if any!); moreover, the few changes that you might have to do will ensure that your app will run more easily on other platforms.

Dependencies

If you don’t already have done it, you should describe your dependencies in a file called Gemfile, located at the top of your application code. Those dependencies will be installed automatically when you push your code.

Rails Applications

Those applications should work out of the box. If you want to learn more about the way passenger handles Rails apps, you can read the passenger RoR doc for details.

Other Rack Applications

Other frameworks will work as easily, as long as they implement the Rack interface). You will need to create a config.ru file (if one is not already supplied with your application).

If you need to create such a file from scratch, check the passenger Rack doc for details, or get some inspiration from the example above.

Note

The Rack specification requires a config.ru file, but also a couple of directories named public and tmp (even if they are empty). Don’t forget to create them if you are trying to deploy, e.g., a simple Sinatra app!

Unsupported gems and how to exclude them

Some Ruby gems are not suited to environments like dotCloud, and should not be installed. Those are gems like:

  • linecache19 (which is only used for debugging purposes, and should not be present on a production environment);
  • SystemTimer.

Actually, if you try to install them anyway, you will generally get a “permission denied” without much dire consequences.

To exclude those gems without juggling with multiple Gemfiles, you can put them in groups, and then tell bundler to exclude them when deploying on dotCloud.

You will need to edit your Build File. Assuming that your Ruby service is named “www”, modify its section like the following example:

www:
  type: ruby
  exclude_bundler_groups:
    - development

Then, in your Gemfile, regroup the unwanted gems in a group:

group :development do
   gem "ruby-debug19"
   gem "my-funky-gem"
end

If you want to learn more about it, feel free to read:

Using Specific Settings on your DotCloud Deployment

To support switching from development to production without changing a lot of things in your code (database servers, directories, etc.), Rack applications use the RACK_ENV environment variable.

Rail applications will have multiple environments defined in the “config/environments” directory: typically, “production.rb”, “test.rb”, etc.

The default value for RACK_ENV is “production”; if you want to set it to something else (e.g. if you have multiple production environments, and need to use different database settings on DotCloud), you can set the RACK_ENV variable when you deploy your service with the following Build File directive:

www:
  type: ruby
  approot: helloruby
  config:
    rack-env: noodles

Use a specific version of Ruby

If you don’t like the default version of Ruby used by your ruby or ruby-worker service, you can switch to another one. Here is how.

Edit your dotcloud.yml file to include a “ruby-version” parameter in the config section:

hello:
  type: ruby
  config:
    ruby-version: X

X can be one of the following:

  • ree – for Ruby Enterprise Edition (1.8 series);
  • 1.9.2 – for “plain” Ruby 1.9.2 (the default);
  • 1.9.3 – for “plain” Ruby 1.9.3.

Note

If you ask for a non-existent version, the deployment will fail. So please don’t try it!

However, if you specify a non-existent parameter (for example, if you use ruby_version instead of ruby-version), the parameter will be silently ignored, for back-and-forth compatibility reasons.

Warning

Like all the “config” parameters, the ruby-version cannot be changed on a live service. You have to destroy the service and push it again with a new configuration in order to change ruby-version.

Running cron jobs

We use the Ruby Version Manager (RVM) to manage the different versions of Ruby that you can use on the ruby service. This causes some problems when you want to run cron jobs. In order to use the correct version of Ruby, you need to first tell cron what Ruby version to use. There are a few different ways of doing this, but we will recommend the most straightforward way here.

To use an RVM Ruby from cron, we need to invoke our own bash session, like so:

MAILTO='me@example.com'

# cron job that runs every minute.
# m h dom mon dow command
* * * * * /bin/bash -l -c '~/current/cron_command.rb'

/bin/bash -l -c Explained

We are wrapping our command in a bash session. The -c option tells bash a command follows. The -l option tells bash to load the entire environment. This option is crucial. Leave out the -l and you won’t load the correct version of Ruby.

The wrapper is necessary because cron runs a very limited environment. RVM relies on environment variables to find Ruby, gems and gem executables.

bash -l brings all this into cron’s environment, so RVM just works. You don’t have to worry about PATH, gem executables, etc. They all work just like they do in your interactive bash sessions.

Important note: in most cases, you’ll want to use single quotes for the command you pass to bash.

For more information about running cron jobs on dotCloud, checkout the periodic tasks guide.

Custom Nginx Configuration

You can specify custom rewrite rules (and actually almost any nginx setting) by creating a file named nginx.conf at the top of your app.

This file will be included by nginx.

Note

You should not include a whole nginx configuration: just the snippets that you need!

A typical example would be:

rewrite ^/search/(.*) /engine/?q=$1 ;

Check out the Nginx wiki to see all available options.

Note

Already have some Apache mod_rewrite RewriteRule statements? All of them can be converted to nginx configuration.