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

Ruby

Note

CLI Command examples on this page are always provided without the --application (shorthand -A) argument, assuming you’re running these commands in a connected folder (at creation or using the dotcloud connect command). For more details on connected folders, see Migrating to the CLI 0.9.

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

That includes modern Ruby web frameworks such as Ruby on 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:

mkdir ramen-on-dotcloud
cd ramen-on-dotcloud
dotcloud create ramen

A dotCloud application is described by a Build File (dotcloud.yml), 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

URLs will be generated for each web service in our application. 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 haven’t already, 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. You can learn more about the way passenger handles Rails apps in the 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 supplied with your application).

If you need to create such a file from scratch, check the passenger Rack docs 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 for 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 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.

Rails 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

Warning

The config dictionary of a service is applied when your service is launched for the first time. If you change it, you will need to destroy the concerned service and push your application again to apply the changes.

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 will have to destroy the service and push it again with the 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.