Subsecciones

Introducción

Prerequisitos

Estos son los prerequisitos (Octubre 2013)
  1. Basic Ruby knowledge, including an installed version of Ruby 2.0.0, Rubygems, and Bundler.
  2. Basic Git knowledge
  3. Your application must run on Ruby (MRI) 2.0.0.
  4. Your application must use Bundler.
  5. A Heroku user account.

Instala el Heroku Toolbelt

  1. Crea una cuenta en Heroku
  2. El Heroku Toolbelt se compone de:
    1. Heroku client - CLI tool for creating and managing Heroku apps
    2. Foreman - an easy option for running your apps locally
    3. Git - revision control and pushing to Heroku

La primera vez te pedirá las credenciales:

$ heroku login
Enter your Heroku credentials.
Email: adam@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
La clave la cargas en la sección SSH keys add key de https://dashboard.heroku.com/account

[~/rack/rack-rock-paper-scissors(test)]$ heroku --version
heroku-gem/2.39.4 (x86_64-darwin11.4.2) ruby/1.9.3

[~/local/src/ruby/sinatra/rack/rack-rock-paper-scissors(test)]$  which heroku
/Users/casiano/.rvm/gems/ruby-1.9.3-p392/bin/heroku
[~/local/src/ruby/sinatra/rack/rack-rock-paper-scissors(test)]$ ruby -v
ruby 1.9.3p392 (2013-02-22 revision 39386) [x86_64-darwin11.4.2]
Seguramente tienes que instalar una versión del toolbet por cada versión de Ruby con la que quieras usarlo.

Para desinstalarlo:

$ gem uninstall heroku --all

Actualizaciones

The Heroku Toolbelt will automatically keep itself up to date.

  1. When you run a heroku command, a background process will be spawned that checks a URL for the latest available version of the CLI.
  2. If a new version is found, it will be downloaded and stored in ~/.heroku/client.
  3. This background check will happen at most once every 5 minutes.
  4. The heroku binary will check for updated clients in ~/.heroku/client before loading the system-installed version.

Ayuda

[~/local/src/ruby/sinatra/rack/rack-rock-paper-scissors(master)]$ heroku --help
Usage: heroku COMMAND [--app APP] [command-specific-options]

Primary help topics, type "heroku help TOPIC" for more details:

  addons    #  manage addon resources
  apps      #  manage apps (create, destroy)
  auth      #  authentication (login, logout)
  config    #  manage app config vars
  domains   #  manage custom domains
  logs      #  display logs for an app
  ps        #  manage dynos (dynos, workers)
  releases  #  manage app releases
  run       #  run one-off commands (console, rake)
  sharing   #  manage collaborators on an app

Additional topics:

  account      #  manage heroku account options
  certs        #  manage ssl endpoints for an app
  db           #  manage the database for an app
  drains       #  display syslog drains for an app
  fork         #  clone an existing app
  git          #  manage git for apps
  help         #  list commands and display help
  keys         #  manage authentication keys
  labs         #  manage optional features
  maintenance  #  manage maintenance mode for an app
  pg           #  manage heroku-postgresql databases
  pgbackups    #  manage backups of heroku postgresql databases
  plugins      #  manage plugins to the heroku gem
  regions      #  list available regions
  stack        #  manage the stack for an app
  status       #  check status of heroku platform
  update       #  update the heroku client
  version      #  display version

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 Gemfile.

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 a Sinatra app:

source "https://rubygems.org"
ruby "2.0.0"
gem 'sinatra', '1.1.0'

[~/sinatra/rockpaperscissors(master)]$ cat Gemfile
source 'https://rubygems.org'
gem 'sinatra'
gem 'haml'
gem 'puma'

Run bundle install to set up your bundle locally.

  1. Run:
    $ bundle install
    
  2. This ensures that all gems specified in Gemfile, together with their dependencies, are available for your application.
  3. Running bundle install also generates a Gemfile.lock file, which should be added to your git repository.
  4. Gemfile.lock ensures that your deployed versions of gems on Heroku match the version installed locally on your development machine.

Declare process types with Procfile

Process types are declared via a file named Procfile placed in the root of your app.

Its format is one process type per line, with each line containing:

<process type>: <command>
The syntax is defined as:

  1. <process type> – an alphanumeric string, is a name for your command, such as
    1. web,
    2. worker,
    3. urgentworker,
    4. clock, etc.
  2. <command> – a command line to launch the process, such as rake jobs:work.
The web process type is special as it’s the only process type that will receive HTTP traffic from Heroku’s routers.

  1. 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.

  2. Assume for instance, that we wanto to execute web.rb using Ruby. Here’s a Procfile:
    web: bundle exec ruby web.rb -p $PORT
    
  3. If we are instead deploying a straight Rack app, here’s a Procfile that can execute our config.ru:
    web: bundle exec rackup config.ru -p $PORT
    

    [~/sinatra/rockpaperscissors(spec)]$ cat config.ru 
    #\ -s puma
    require './rps'
    run RockPaperScissors::App
    

  1. This declares a single process type, web, and the command needed to run it.
  2. 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.

Foreman

  1. It’s important when developing and debugging an application that the local development environment is executed in the same manner as the remote environments.

  2. This ensures that incompatibilities and hard to find bugs are caught before deploying to production and treats the application as a holistic unit instead of a series of individual commands working independently.

  3. Foreman is a command-line tool for running Procfile-backed apps. It’s installed automatically by the Heroku Toolbelt.

  4. If you had a Procfile with both web and worker process types, Foreman will start one of each process type, with the output interleaved on your terminal

  5. We can now start our 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
    
  6. Our app will come up on port 5000. Test that it’s working with curl or a web browser, then Ctrl-C to exit.

Setting local environment variables

Config vars saved in the .env file of a project directory will be added to the environment when run by Foreman.

For example we can set the RACK_ENV to development in your environment.

$ echo "RACK_ENV=development" >>.env
$ foreman run irb
> puts ENV["RACK_ENV"]
> development
Do not commit the .env file to source control. It should only be used for local configuration.

Procfile y Despliegue

Véase la descripción de los contenidos del Procfile en 58.1.

  1. A Procfile is not necessary to deploy apps written in most languages supported by Heroku.

  2. The platform automatically detects the language, and creates a default web process type to boot the application server.

  3. Creating an explicit Procfile is recommended for greater control and flexibility over your app.

  4. For Heroku to use your Procfile, add the Procfile to the root of your application, then push to Heroku:

    $ git add .
    $ git commit -m "Procfile"
    $ git push heroku
    ...
    -----> Procfile declares process types: web, worker
           Compiled slug size is 10.4MB
    -----> Launching... done
           http://strong-stone-297.herokuapp.com deployed to Heroku
    
    To git@heroku.com:strong-stone-297.git
     * [new branch]      master -> master
    

Store your app in Git

$ git init
$ git add .
$ git commit -m "init"

[~/sinatra/rockpaperscissors(master)]$ git remote -v
origin  git@github.com:crguezl/sinatra-rock-paper-scissors.git (fetch)
origin  git@github.com:crguezl/sinatra-rock-paper-scissors.git (push)

Deploy your application to Heroku

Create the app on Heroku:

[~/sinatra/rockpaperscissors(master)]$ heroku create
Creating mysterious-falls-4594... done, stack is cedar
http://mysterious-falls-4594.herokuapp.com/ | git@heroku.com:mysterious-falls-4594.git
Git remote heroku added

[~/sinatra/rockpaperscissors(spec)]$ cat Rakefile 
desc "start server using rackup ..."
task :default do
  sh "rackup"
end

require 'rspec/core/rake_task'

RSpec::Core::RakeTask.new do |task|
  task.rspec_opts = ["-c", "-f progress"] 
  task.pattern    = 'spec/**/*_spec.rb'
end

[~/sinatra/rockpaperscissors(master)]$ git remote -v
heroku  git@heroku.com:mysterious-falls-4594.git (fetch)
heroku  git@heroku.com:mysterious-falls-4594.git (push)
origin  git@github.com:crguezl/sinatra-rock-paper-scissors.git (fetch)
origin  git@github.com:crguezl/sinatra-rock-paper-scissors.git (push)

Deploy your code:

[~/sinatra/rockpaperscissors(master)]$ git push heroku master
Counting objects: 31, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (29/29), done.
Writing objects: 100% (31/31), 9.09 KiB, done.
Total 31 (delta 11), reused 0 (delta 0)

-----> Ruby/Rack app detected
-----> 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 tilt (1.4.1)
       Installing haml (4.0.3)
       Installing rack (1.5.2)
       Installing puma (2.0.1)
       Installing rack-protection (1.5.0)
       Installing sinatra (1.4.2)
       Using bundler (1.3.2)
       Your bundle is complete! It was installed into ./vendor/bundle
       Post-install message from haml:
       HEADS UP! Haml 4.0 has many improvements, but also has changes that may break
       your application:
       * Support for Ruby 1.8.6 dropped
       * Support for Rails 2 dropped
       * Sass filter now always outputs <style> tags
       * Data attributes are now hyphenated, not underscored
       * html2haml utility moved to the html2haml gem
       * Textile and Maruku filters moved to the haml-contrib gem
       For more info see:
       http://rubydoc.info/github/haml/haml/file/CHANGELOG.md
       Cleaning up the bundler cache.
-----> Discovering process types
       Procfile declares types     -> (none)
       Default types for Ruby/Rack -> console, rake, web

-----> Compiled slug size: 1.3MB
-----> Launching... done, v4
       http://mysterious-falls-4594.herokuapp.com deployed to Heroku

To git@heroku.com:mysterious-falls-4594.git
 * [new branch]      master -> master
[~/sinatra/rockpaperscissors(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
Veamos que dice la ayuda:
$ heroku help ps
Usage: heroku ps

 list processes for an app

Additional commands, type "heroku help COMMAND" for more details:

  ps:restart [PROCESS]           #  ps:restart [PROCESS]
  ps:scale PROCESS1=AMOUNT1 ...  #  ps:scale PROCESS1=AMOUNT1 ...
  ps:stop PROCESS                #  ps:stop PROCESS

$ heroku help ps:scale
Usage: heroku ps:scale PROCESS1=AMOUNT1 ...

 scale processes by the given amount

 Example: heroku ps:scale web=3 worker+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.
[~/sinatra/sinatra-rock-paper-scissors/sinatra-rockpaperscissors(master)]$ heroku ps
Process  State        Command                               
-------  -----------  ------------------------------------  
web.1    idle for 8h  bundle exec rackup config.ru -p $P..

We can now visit the app in our browser with heroku open.

[~/sinatra/rockpaperscissors(master)]$ heroku open
Opening http://mysterious-falls-4594.herokuapp.com/
[~/sinatra/rockpaperscissors(master)]$

Dyno sleeping and scaling

  1. Having only a single web dyno running will result in the dyno going to sleep after one hour of inactivity.

  2. This causes a delay of a few seconds for the first request upon waking.

  3. Subsequent requests will perform normally.

  4. To avoid this, you can scale to more than one web dyno. For example:
    $ heroku ps:scale web=2
    
  5. For each application, Heroku provides 750 free dyno-hours.

  6. 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:

$ 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 run bash

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.

Since your app is - in general - spread across many dynos by the dyno manager, there is no single place to SSH into.

You deploy and manage apps, not servers.

You can invoke a shell as a one-off dyno.

While the web dyno would be defined in the Procfile and managed by the platform, the console and script would only be executed when needed. These are one-off dynos.

There are differences between one-off dynos (run with heroku run) and formation dynos

  1. One-off dynos run attached to your terminal, with a character-by-character TCP connection for STDIN and STDOUT. This allows you to use interactive processes like a console.
  2. Since STDOUT is going to your terminal, the only thing recorded in the app’s logs is the startup and shutdown of the dyno.
  3. One-off dynos terminate as soon as you press Ctrl-C or otherwise disconnect in your local terminal.
  4. One-off dynos never automatically restart, whether the process ends on its own or whether you manually disconnect.
  5. One-off dynos are named in the scheme run.N rather than the scheme <process-type>.N.
  6. One-off dynos can never receive HTTP traffic, since the routers only routes traffic to dynos named web.N.

[~/srcPLgrado/pegjscalc(master)]$ heroku run bash
Running `bash` attached to terminal... up, run.2966
~ $ uname -a
Linux 8f9f0a0c-b10d-4cd5-9c1e-8e87067b6be2 3.8.11-ec2 #1 SMP Fri May 3 09:11:15 UTC 2013 x86_64 GNU/Linux
[~/srcPLgrado/pegjscalc(master)]$ heroku run bash
Running `bash` attached to terminal... up, run.2966
~ $ ls -l
total 48
drwx------ 2 u20508 20508 4096 2014-03-24 11:23 bin
-rw------- 1 u20508 20508   42 2014-03-24 11:23 config.ru
-rw------- 1 u20508 20508  258 2014-03-24 11:23 Gemfile
-rw------- 1 u20508 20508 2399 2014-03-24 11:23 Gemfile.lock
-rw------- 1 u20508 20508 1152 2014-03-24 11:23 main.rb
-rw------- 1 u20508 20508   43 2014-03-24 11:23 Procfile
drwx------ 2 u20508 20508 4096 2014-03-24 11:23 public
-rw------- 1 u20508 20508  492 2014-03-24 11:23 Rakefile
-rw------- 1 u20508 20508  421 2014-03-24 11:23 README.md
drwx------ 2 u20508 20508 4096 2014-03-24 11:23 tmp
drwx------ 5 u20508 20508 4096 2014-03-24 11:23 vendor
drwx------ 2 u20508 20508 4096 2014-03-24 11:23 views

~ $ ls -l tmp/
total 4
-rw------- 1 u20508 20508 242 2014-03-24 11:23 heroku-buildpack-release-step.yml
~ $ ls -l vendor
total 12
drwx------ 4 u20508 20508 4096 2014-03-20 23:33 bundle
drwx------ 2 u20508 20508 4096 2014-03-20 23:33 heroku
drwx------ 6 u20508 20508 4096 2014-03-24 11:23 ruby-2.0.0

~ $ ls -l bin
total 0
lrwxrwxrwx 1 u20508 20508 28 2014-03-24 15:05 erb -> ../vendor/ruby-2.0.0/bin/erb
lrwxrwxrwx 1 u20508 20508 28 2014-03-24 15:05 gem -> ../vendor/ruby-2.0.0/bin/gem
lrwxrwxrwx 1 u20508 20508 28 2014-03-24 15:05 irb -> ../vendor/ruby-2.0.0/bin/irb
lrwxrwxrwx 1 u20508 20508 29 2014-03-24 15:05 rake -> ../vendor/ruby-2.0.0/bin/rake
lrwxrwxrwx 1 u20508 20508 29 2014-03-24 15:05 rdoc -> ../vendor/ruby-2.0.0/bin/rdoc
lrwxrwxrwx 1 u20508 20508 27 2014-03-24 15:05 ri -> ../vendor/ruby-2.0.0/bin/ri
lrwxrwxrwx 1 u20508 20508 29 2014-03-24 15:05 ruby -> ../vendor/ruby-2.0.0/bin/ruby
lrwxrwxrwx 1 u20508 20508 33 2014-03-24 15:05 ruby.exe -> ../vendor/ruby-2.0.0/bin/ruby.exe
lrwxrwxrwx 1 u20508 20508 31 2014-03-24 15:05 testrb -> ../vendor/ruby-2.0.0/bin/testrb

heroku run console

  1. 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.

  2. 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>
    
  3. By default, 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
    

[~/srcPLgrado/pegjscalc(master)]$ heroku run irb
Running `irb` attached to terminal... up, run.1081
irb(main):001:0> ENV.keys
=> ["DATABASE_URL", "SHLVL", "PORT", "HOME", "HEROKU_POSTGRESQL_BROWN_URL", "PS1", "_", "COLUMNS", "RACK_ENV", "TERM", "PATH", "LANG", "GEM_PATH", "PWD", "LINES", "DYNO"]
irb(main):002:0> ENV["DATABASE_URL"]
=> "postgres://moiwgreelvvujc:GL3shXGOpURyWOPrS2G8qaxzUe@ec2-23-21-101-129.compute-1.amazonaws.com:5432/dat9smslrg6g0a"
irb(main):003:0> ENV["HEROKU_POSTGRESQL_BROWN_URL"]
=> "postgres://moiwgreelvvujc:GL3shXGOpURyWOPrS2G8qaxzUe@ec2-23-21-101-129.compute-1.amazonaws.com:5432/dat9smslrg6g0a"
irb(main):004:0>
Podemos cargar librerías de nuestra aplicación (véase pegjscalc) y usarlas.
[~/srcPLgrado/pegjscalc(master)]$ heroku run console
Running `console` attached to terminal... up, run.9013
irb(main):002:0> require './main'
=> true
irb(main):003:0> p = PL0Program.all
=> [#<PL0Program @name="3p2m1" @source="                    3-2-1\r\n          ">, #<PL0Program @name="apbtc" @source="a+b*c">]
irb(main):005:0> chuchu = PL0Program.first(:name => "apbtc")
=> #<PL0Program @name="apbtc" @source="a+b*c">
irb(main):006:0> chuchu.source
=> "a+b*c"
irb(main):007:0> prog = PL0Program.create(:name => "tata", :source => "3*a-c")
=> #<PL0Program @name="tata" @source="3*a-c">
irb(main):008:0>

Rake

Rake can be run in an attached dyno exactly like the console:

[~/srcPLgrado/pegjscalc(master)]$ heroku run rake -T
Running `rake -T` attached to terminal... up, run.2124
rake clean  # Remove pl0.pegjs
rake sass   # Compile public/styles.scss into public/styles.css using sass
rake test   # tests
rake web    # Compile pl0.pegjs browser version
[~/srcPLgrado/pegjscalc(master)]$ heroku run rake test
Running `rake test` attached to terminal... up, run.2082
Not implemented (yet)

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 you don’t need any database at all.

If you need a SQL database for your app, do this:

  1. $ heroku addons:add heroku-postgresql:dev
    
  2. You must also add the Postgres gem to your app in order to use your database. Add a line to your Gemfile like this:
    gem 'pg'
    
  3. You’ll also want to setup a local PostgreSQL database.

Webserver

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, they recommend Unicorn as the webserver.

Casiano Rodríguez León
2015-01-25