Table of Contents
- Local workstation setup
- Write your app
- Specify Ruby Version and Declare dependencies with a Gemfile
- Declare process types with Procfile
- Store your app in Git
- Deploy your application to Heroku
- Visit your application
- Dyno sleeping and scaling
- View the logs
- Using a SQL database
- Next steps
This quickstart will get you going with Ruby and the Sinatra web framework, deployed to Heroku. For Rails applications, please see Getting Started with Rails 4.x on Heroku. For general information on how to develop and architect apps for use on Heroku, see Architecting Applications for Heroku.
If you have questions about Ruby on Heroku, consider discussing it in the Ruby on Heroku forums.
- Basic Ruby knowledge, including an installed version of Ruby 2.0.0, Rubygems, and Bundler.
- Basic Git knowledge
- Your application must run on Ruby (MRI) 2.0.0.
- Your application must use Bundler.
- A Heroku user account. Signup is free and instant.
Local workstation setup
Once installed, you use the
heroku command from your command shell. Log in using the email address and password you used when creating your Heroku account:
$ heroku login Enter your Heroku credentials. Email: email@example.com Password: Could not find an existing public key. Would you like to generate one? [Yn] Generating new SSH public key. Uploading ssh public key /Users/adam/.ssh/id_rsa.pub
Press enter at the prompt to upload your existing
ssh key or create a new one, used for pushing code later on.
Write your app
You may be starting from an existing app. If not, here’s a “hello, world” sourcefile you can use:
require 'sinatra' get '/' do "Hello, world" end
Specify Ruby Version and Declare dependencies with a Gemfile
Heroku recognizes an app as Ruby by the existence of a
Gemfile. Even if your app has no gem dependencies, you should still create an empty
Gemfile in order that it appear as a Ruby app.
In local testing, you should be sure to run your app in an isolated environment (via
bundle exec or an empty RVM gemset), to make sure that all the gems your app depends on are in the
In addition to specifying dependencies, you’ll want to specify your Ruby Version using the
ruby DSL provided by Bundler.
Here’s an example
Gemfile for the Sinatra app we created above:
source "https://rubygems.org" ruby "2.0.0" gem 'sinatra', '1.1.0'
bundle install to set up your bundle locally.
Declare process types with Procfile
Use a Procfile, a text file in the root directory of your application, to explicitly declare what command should be executed to start a web dyno. In this case, you simply need to execute the
web.rb using Ruby.
Procfile for the sample app we’ve been working on:
web: bundle exec ruby web.rb -p $PORT
If you’re instead deploying a straight Rack app, here’s a
Procfile that can execute your
web: bundle exec rackup config.ru -p $PORT
This declares a single process type,
web, and the command needed to run it. The name “web” is important here. It declares that this process type will be attached to the HTTP routing stack of Heroku, and receive web traffic when deployed.
You can now start your application locally using Foreman (installed as part of the Toolbelt):
$ foreman start 16:39:04 web.1 | started with pid 30728 18:49:43 web.1 | [2013-03-12 18:49:43] INFO WEBrick 1.3.1 18:49:43 web.1 | [2013-03-12 18:49:43] INFO ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-linux] 18:49:43 web.1 | [2013-03-12 18:49:43] INFO WEBrick::HTTPServer#start: pid=30728 port=5000
Your app will come up on port 5000. Test that it’s working with
curl or a web browser, then Ctrl-C to exit.
Store your app in Git
We now have the three major components of our app: dependencies in
Gemfile, process types in
Procfile, and our application source in
web.rb. Let’s put it into Git:
$ git init $ git add . $ git commit -m "init"
Deploy your application to Heroku
Create the app on Heroku:
$ heroku create Creating blazing-galaxy-997... done, stack is cedar http://blazing-galaxy-997.herokuapp.com/ | firstname.lastname@example.org:blazing-galaxy-997.git Git remote heroku added
Deploy your code:
$ git push heroku master Counting objects: 6, done. Delta compression using up to 4 threads. Compressing objects: 100% (5/5), done. Writing objects: 100% (6/6), 660 bytes, done. Total 6 (delta 0), reused 0 (delta 0) -----> Ruby/Rack app detected -----> Using Ruby version: ruby-2.0.0 -----> Installing dependencies using Bundler version 1.3.2 Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin --deployment Fetching gem metadata from https://rubygems.org/.......... Fetching gem metadata from https://rubygems.org/.. Installing rack (1.2.2) Installing tilt (1.3) Installing sinatra (1.1.0) Using bundler (1.3.2) Your bundle is complete! It was installed into ./vendor/bundle Cleaning up the bundler cache. -----> Discovering process types Procfile declares types -> web Default types for Ruby/Rack -> console, rake -----> Compiled slug size: 25.1MB -----> Launching... done, v3 http://blazing-galaxy-997.herokuapp.com deployed to Heroku To email@example.com:blazing-galaxy-997.git * [new branch] master -> master
Visit your application
You’ve deployed your code to Heroku, and specified the process types in a
Procfile. You can now instruct Heroku to execute a process type. Heroku does this by running the associated command in a dyno - a lightweight container which is the basic unit of composition on Heroku.
Let’s ensure we have one dyno running the
web process type:
$ heroku ps:scale web=1
You can check the state of the app’s dynos. The
heroku ps command lists the running dynos of your application:
$ heroku ps === web: `bundle exec ruby web.rb -p $PORT` web.1: up for 9m
Here, one dyno is running.
We can now visit the app in our browser with
$ heroku open Opening blazing-galaxy-997... done
Dyno sleeping and scaling
Having only a single web dyno running will result in the dyno going to sleep after one hour of inactivity. This causes a delay of a few seconds for the first request upon waking. Subsequent requests will perform normally.
To avoid this, you can scale to more than one web dyno. For example:
$ heroku ps:scale web=2
For each application, Heroku provides 750 free dyno-hours. Running your app at 2 dynos would exceed this free, monthly allowance, so let’s scale back:
$ heroku ps:scale web=1
View the logs
Heroku treats logs as streams of time-ordered events aggregated from the output streams of all the dynos running the components of your application. Heroku’s Logplex provides a single channel for all of these events.
View information about your running app using one of the logging commands,
$ heroku logs 2013-03-13T04:10:49+00:00 heroku[web.1]: Starting process with command `bundle exec ruby web.rb -p 25410` 2013-03-13T04:10:50+00:00 app[web.1]: [2013-03-13 04:10:50] INFO WEBrick 1.3.1 2013-03-13T04:10:50+00:00 app[web.1]: [2013-03-13 04:10:50] INFO ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-linux] 2013-03-13T04:10:50+00:00 app[web.1]: [2013-03-13 04:10:50] INFO WEBrick::HTTPServer#start: pid=2 port=25410
Heroku allows you to run commands in a one-off dyno - scripts and applications that only need to be executed when needed - using the
heroku run command. You can use this to launch an interactive Ruby shell (
bundle exec irb) attached to your local terminal for experimenting in your app’s environment:
$ heroku run console Running `console` attached to terminal... up, ps.1 irb(main):001:0>
irb has nothing loaded other than the Ruby standard library. From here you can
require some of your application files. Or you can do it on the command line:
$ heroku run console -r ./web
Rake can be run in an attached dyno exactly like the console:
$ heroku run rake db:migrate
Using a SQL database
By default, non-Rails apps aren’t given a SQL database. This is because you might want to use a NoSQL database like Redis or CouchDB, or (as in the case of our sample app above) you don’t need any database at all. If you need a SQL database for your app, do this:
$ heroku addons:add heroku-postgresql:dev
You must also add the Postgres gem to your app in order to use your database. Add a line to your
Gemfile like this:
You’ll also want to setup a local PostgreSQL database.
By default, Ruby buffers its output to
stdout. To take advantage of Heroku’s realtime logging, you will need to disable this buffering to have log messages sent straight to Logplex. To disable this buffering add this to your
$stdout.sync = true
By default your app (Rack) will use Webrick. This is fine for testing, but for production apps you’ll want to switch to a more robust webserver. On Cedar, we recommend Unicorn as the webserver.
If you push your app and it crashes (
heroku ps shows state
crashed), check your logs to find out what went wrong. Here are some common problems.
Failed to require a sourcefile
If your app failed to require a sourcefile, chances are good you’re running Ruby 1.9.1 or 1.8 in your local environment. The load paths have changed in Ruby 1.9 which applies to Ruby 2.0. Port your app forward to Ruby 2.0.0 making certain it works locally before trying to push to Cedar again.
Ruby 1.9 added more sophisticated encoding support to the language which applies to Ruby 2.0. Not all gems work with Ruby 2.0. If you hit an encoding error, you probably haven’t fully tested your app with Ruby 2.0.0 in your local environment. Port your app forward to Ruby 2.0.0 making certain it works locally before trying to push to Cedar again.
Missing a gem
If your app crashes due to missing a gem, you may have it installed locally but not specified in your
Gemfile. You must isolate all local testing using
bundle exec. For example, don’t run
ruby web.rb, run
bundle exec ruby web.rb. Don’t run
rake db:migrate, run
bundle exec rake db:migrate.
Another approach is to create a blank RVM gemset to be absolutely sure you’re not touching any system-installed gems:
$ rvm gemset create myapp $ rvm gemset use myapp
Runtime dependencies on development/test gems
If you’re still missing a gem when you deploy, check your Bundler groups. Heroku builds your app without the
test groups, and if you app depends on a gem from one of these groups to run, you should move it out of the group.
One common example using the RSpec tasks in your
Rakefile. If you see this in your Heroku deploy:
$ heroku run rake -T Running `rake -T` attached to terminal... up, ps.3 rake aborted! no such file to load -- rspec/core/rake_task
Then you’ve hit this problem. First, duplicate the problem locally like so:
$ bundle install --without development:test ... $ bundle exec rake -T rake aborted! no such file to load -- rspec/core/rake_task
Now you can fix it by making these Rake tasks conditional on the gem load. For example:
begin require "rspec/core/rake_task" desc "Run all examples" RSpec::Core::RakeTask.new(:spec) do |t| t.rspec_opts = %w[--color] t.pattern = 'spec/*_spec.rb' end rescue LoadError end
Confirm it works locally, then push to Heroku.
- Visit the Ruby category to learn more about deploying Ruby applications.
- Read How Heroku Works for a technical overview of the concepts you’ll encounter while writing, configuring, deploying and running applications.