momota.txt

hello, hello, hello, how low?

Rails から外れた僕らは Sinatra で I Did It My Way (3)

sinatra

今回はこれまで作った sinatra アプリケーションを PaaS の heroku へデプロイする。 事前に heroku には sign up しておこう。

最初にできあがりを示す。

heroku: http://sample-mongo-app.herokuapp.com/

github: https://github.com/momota/heroku_sinatra_sample


heroku toolbelt をインストールする

heroku へデプロイするために heroku toolbelt をインストールする。 heroku toolbelt は https://toolbelt.heroku.com/ から環境にあったやり方を選んでインストールする。mac ではインストーラが .pkg 形式で配布されているので、それをぽちぽちクリックして進めればよい。

なお、heroku toolbelt には、以下が含まれている。

  • heroku client: heroku アプリケーションを作成したり、管理したりする CLI ツール
  • foreman: procfile ベースでアプリケーションの管理をする
  • git

shell でバージョン確認してインストールできたかを確認する。

1
2
$ heroku --version
heroku-toolbelt/2.41.0 (x86_64-darwin10.8.0) ruby/1.9.3

インストールできているようだ。

heroku login

heroku login で heroku への認証を通したり、ssh キーを登録したりする。

1
2
3
4
5
$ heroku login
Enter your Heroku credentials.
Email: makoto.momota@gmail.com
Password (typing will be hidden): ENTER_YOUR_HEROKU_PASSWORD
Authentication successful.

私の場合は、すでにキー登録していたので、なにもキー登録操作がなかったが、初回実行の際は、以下のような感じになるらしい。

1
2
3
4
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

foreman で sinatra が起動できるか確認する

foreman で複数の sinatra アプリケーション を管理したり、アプリケーションごとに異なる起動方法を単一に wrapping できる。 heroku では、アプリケーションを起動するために foreman が必須のようだ。 foreman でのアプリケーション起動には、 Procfile を書く必要がある。書式は アプリケーション名: コマンド を改行区切りで列挙していく。

ここでは、mongo_app.rb を起動するので、以下のように記述する。

1
web: bundle exec ruby mongo_app.rb -p $PORT

お試しに、ローカルで foreman start により sinatra アプリケーションを起動する。

1
2
3
4
5
6
$ foreman start
17:25:31 web.1  | started with pid 10879
17:25:33 web.1  | [2013-09-23 17:25:33] INFO  WEBrick 1.3.1
17:25:33 web.1  | [2013-09-23 17:25:33] INFO  ruby 2.0.0 (2013-06-27) [x86_64-darwin12.4.0]
17:25:33 web.1  | == Sinatra/1.4.3 has taken the stage on 5000 for development with backup from WEBrick
17:25:33 web.1  | [2013-09-23 17:25:33] INFO  WEBrick::HTTPServer#start: pid=10879 port=5000

5000 番ポートで起動したので、http://localhost:5000/ にアクセスしてみる。問題なさそう。

git リポジトリを作成して push する

heroku デプロイには git が必須。 git でバージョン管理していなければ、git init して始めよう。

1
2
3
$ git init
$ git add .
$ git commit -m 'your commit message'

heroku へデプロイする

いよいよ heroku 上にアプリケーションを登録する。アプリケーション名はなしでも任意の名前が付けられるが、ここではsample-mongo-appにした。(のちほど変えることも可能)

1
2
3
4
$ heroku apps:create sample-mongo-app
Creating sample-mongo-app... done, stack is cedar
http://sample-mongo-app.herokuapp.com/ | git@heroku.com:sample-mongo-app.git
Git remote heroku added

このコマンドにより以下のように git リモートリポジトリに heroku リポジトリが登録される。

1
2
3
4
5
6
7
$ git remote
heroku
$ git remote show heroku
* remote heroku
Fetch URL: git@heroku.com:sample-mongo-app.git
Push  URL: git@heroku.com:sample-mongo-app.git
HEAD branch: (unknown)

heroku リポジトリに push することで、デプロイできる。なんとシンプルな仕組み。 ちなみに、Gemfile.lock も git で管理してないとデプロイ時にエラーとなる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
$ git push heroku master
Counting objects: 90, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (85/85), done.
Writing objects: 100% (90/90), 126.44 KiB, done.
Total 90 (delta 27), 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 backports (3.3.4)
       Installing bson (1.9.2)
       Installing bson_ext (1.9.2)
       Installing eventmachine (1.0.3)
       Installing mongo (1.9.2)
       Installing rack (1.5.2)
       Installing rack-protection (1.5.0)
       Installing rack-test (0.6.2)
       Installing tilt (1.4.1)
       Installing sinatra (1.4.3)
       Installing sinatra-contrib (1.4.0)
       Using bundler (1.3.2)
       Your bundle is complete! It was installed into ./vendor/bundle
       Cleaning up the bundler cache.
-----> WARNINGS:
       You have not declared a Ruby version in your Gemfile.
       To set your Ruby version add this line to your Gemfile:
       ruby '2.0.0'
       # See https://devcenter.heroku.com/articles/ruby-versions for more information."
-----> Discovering process types
       Procfile declares types     -> web
       Default types for Ruby/Rack -> console, rake

-----> Compiled slug size: 26.4MB
-----> Launching... done, v3
       http://sample-mongo-app.herokuapp.com deployed to Heroku

To git@heroku.com:sample-mongo-app.git
 * [new branch]      master -> master

mongodb を heroku で使う

heroku ではさまざまな add-on が提供されており、その中から mongodb のホスティングである MongoHQ を利用する。

add-on を利用するにはクレジットカード情報の登録が必要となるので、済ませておく。https://heroku.com/verify

以下で、add-on の設定をする。ここでは、無料プランの ”sandbox” を選ぶ。

1
2
3
4
5
6
$ heroku addons:add mongohq:sandbox
Adding mongohq:sandbox on sample-mongo-app... done, v4 (free)
Use `heroku addons:docs mongohq` to view documentation.
$ heroku config
=== sample-mongo-app Config Vars
MONGOHQ_URL: mongodb://ID:パスワード@paulo.mongohq.com:10014/データベース名

sinatraの DB 接続部分を mongohq 用に書き換える。

公式サイト通り、 DB コネクションをメソッド化する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
require 'sinatra'
require 'sinatra/reloader'
require 'mongo'
require 'uri'


def get_connection
  return @db_connection if @db_connection
  db = URI.parse(ENV['MONGOHQ_URL'])
  db_name = db.path.gsub(/^\//, '')
  @db_connection = Mongo::Connection.new(db.host, db.port).db(db_name)
  @db_connection.authenticate(db.user, db.password) unless (db.user.nil? || db.user.nil?)
  @db_connection
end

before do
  db_con = get_connection
  @comments = db_con.collection('comments')
end

helpers do
  # escape html
  include Rack::Utils
  alias_method :h, :escape_html
end

get '/' do
  erb :index
end

post '/new' do
  @comments.insert( :body => params[:body] )
  redirect '/'
end

post '/delete' do
  id = BSON::ObjectId( params[:id] )
  @comments.find('_id' => id).each { |d_comment|
    @comments.remove( d_comment )
  }
end

これを前述したとおり、git commit/pushしてあげれば、heroku 上で sinatra アプリケーション 〜 mongodb 間の接続が確認できる。

私がデプロイした sinatra サンプルアプリケーションは、以下からアクセス可能。

http://sample-mongo-app.herokuapp.com/

heroku でのデバッグ

以下でアプリケーションログを tail -f しているように参照できる。

1
$ heroku logs --tail

番外編

heroku gem は将来的に廃止されるようで、heroku toolbelt をインストールすることを推奨する。

(失敗,というか古い情報編) heroku gem をインストールする

Gemfile に gem "heroku" を追記して bundler でインストールする。

1
2
3
4
5
6
7
8
9
diff --git a/Gemfile b/Gemfile
index 74db599..734c191 100644
--- a/Gemfile
+++ b/Gemfile
@@ -8,4 +8,5 @@ gem "sinatra", "1.4.3"
 gem "sinatra-contrib", "1.4.0"
 gem "mongo"
 gem "bson_ext"
+gem "heroku"

bundle install する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
$ bundle install --path vendor/bundle
Fetching gem metadata from https://rubygems.org/...........
Fetching gem metadata from https://rubygems.org/..
Resolving dependencies...
Using i18n (0.6.1)
Using multi_json (1.8.0)
Using activesupport (3.2.13)
Using builder (3.0.4)
Using activemodel (3.2.13)
Using arel (3.0.2)
Using tzinfo (0.3.37)
Using activerecord (3.2.13)
Installing addressable (2.3.5)
Using backports (3.3.4)
Using bson (1.9.2)
Using bson_ext (1.9.2)
Using eventmachine (1.0.3)
Installing excon (0.25.3)
Installing heroku-api (0.3.15)
Installing launchy (2.3.0)
Installing netrc (0.7.7)
Installing mime-types (1.25)
Installing rest-client (1.6.7)
Installing rubyzip (1.0.0)
Installing heroku (2.41.0)
Using mongo (1.9.2)
Using rack (1.5.2)
Using rack-protection (1.5.0)
Using rack-test (0.6.2)
Using tilt (1.4.1)
Using sinatra (1.4.3)
Using sinatra-contrib (1.4.0)
Using sqlite3 (1.3.7)
Using bundler (1.3.5)
Your bundle is complete!
It was installed into ./vendor/bundle
Post-install message from heroku:
 !    The `heroku` gem has been deprecated and replaced with the Heroku Toolbelt.
 !    Download and install from: https://toolbelt.heroku.com
 !    For API access, see: https://github.com/heroku/heroku.rb

なんか heroku gem は、もう廃止されるみたいなメッセージが出た。 アンインストールすることにしよう。

heroku gem アンインストール

Gemfile から先ほど追加した gem "heroku" 行を消す。 そのあとに bundle clean でアンインストールする。

1
2
3
4
5
6
7
8
9
10
11
$ bundle clean
Resolving dependencies...
Removing addressable (2.3.5)
Removing excon (0.25.3)
Removing heroku (2.41.0)
Removing heroku-api (0.3.15)
Removing launchy (2.3.0)
Removing mime-types (1.25)
Removing netrc (0.7.7)
Removing rest-client (1.6.7)
Removing rubyzip (1.0.0)

Comments