LoginSignup
44
41

More than 5 years have passed since last update.

Rails 5 (非beta) + Heroku で作る、無料APIサーバ

Posted at

この記事は、以下のブログ、プロジェクトのまとめです。

Rails 5でのプロジェクト作成

Rails 5の使用

まずは準備。

$ mkdir fetch_rss_and_post_hateblog
$ cd fetch_rss_and_post_hateblog
$ echo "gem 'rails', '~>5.0'" > Gemfile
$ mkdir .bundle
$ echo '---                                                                                                                  
BUNDLE_PATH: vendor/bundle
BUNDLE_DISABLE_SHARED_GEMS: 1
BUNDLE_BIN: ./.bin' > .bundle/config
$ sudo yum install -y sqlite-devel # 必要に応じてapt-getなど
$ bundle install

プロジェクトをセットアップ。

$ rails new . --api
$ echo "development:
  secret_key_base: `rake secret`

test:
  secret_key_base: `rake secret`

production:
  secret_key_base: <%= ENV[\"SECRET_KEY_BASE\"] %>" > config/secrets.yml

ここまでの関係ファイルを一旦プッシュ。

$ gibo osx ruby rails vim >> .gitignore
$ git init
$ git remote add origin git://github.com/user/repo.git
$ git push origin master

APIサーバの作成

RSSを取ってきて、title, URL, descriptionを返すAPIサーバを作ってみます。

$ rails g controller post

APIモードで作られているか確認してみる。


$ cd app
$ ls
channels  controllers  jobs  mailers  views

RSSフィードを取ってきて、JSONで表示してみます。

はてブのRSSフィードを RSS:Parser#parse で取れない件は、 はてなのAPIを使う際に503エラーが出る問題と解決策を参考にしました。

app/controllers/posts_controller.rb
def fetch
  url = 'http://b.hatena.ne.jp/dogwood008/rss'
  ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
  rss = open(url, 'User-Agent' => ua)
  feed = RSS::Parser.parse(rss)
  rss.close
  items = feed.items.map do |i|
    { link: i.link, title: i.title, desc: i.description, date: i.dc_date }
  end
  render json: items
end
config/routes.rb
Rails.application.routes.draw do
  get '/fetch', to: 'posts#fetch'
end

いざ、実行。

$ rails s -b 0.0.0.0

http://localhost:3000/posts/fetch

[{
  link: "http://brevis.exblog.jp/24515937/",
  title: "トラブルには技術的原因と、マネジメント的原因がある : タイム・コンサルタントの日誌から",
  desc: "【要約と私感】“マネジメント的原因” = 仕組みの原因。手っ取り早く直すには技術的要因を取り除けば良いけど、仕組みがダメならまた似たような失敗をうむ。",
  date: "2016-07-10T15:33:53.000+09:00"
},
  {
  link: "http://qiita.com/teradonburi/items/a382a17e1e0245b7d831",
  title: "AWS料金早見表(サーバレスアーキテクチャ) - Qiita",
  desc: "一度自分で一通りやってみたい感ある。",
  date: "2016-07-10T15:27:49.000+09:00"
}, ...]

ヒューッ!!
その他いろいろ作ります。

Herokuへのデプロイ

Getting Started with Rails 5.x on Herokuを参考に進めていきます。

準備

herokuは PostgreSQL を推奨しているので、それに合わせる。

Gemfile
group :production do
  gem 'pg'
end

heroku toolbeltをインストール。

$ wget -O- https://toolbelt.heroku.com/install.sh | sh
$ echo 'PATH="/usr/local/heroku/bin:$PATH"' >> ~/.bash_profile
$ source ~/.bash_profile

ログインします。予めアカウントはWebから作っておく。

$ heroku login
heroku-cli: Installing CLI... 21.83MB/21.83MB
Enter your Heroku credentials.
Email: email@example.com
Password (typing will be hidden):
Logged in as email@example.com

アプリケーションを作成~デプロイ

$ heroku create
Heroku CLI submits usage information back to Heroku. If you would like to disable this, set `skip_analytics: true` in /home/kit/.heroku/config.json
Creating app... done, ⬢ XXXXX-YYYYY-12345
https://XXXXX-YYYYY-12345.herokuapp.com/ | https://git.heroku.com/whispering-YYYYY-12345.git

origin の他に、リモートリポジトリ heroku が追加されます。

$ git remote show heroku
* remote heroku
  Fetch URL: https://git.heroku.com/XXXXX-YYYYY-12345.git
  Push  URL: https://git.heroku.com/XXXXX-YYYYY-12345.git
  HEAD branch: (unknown)

早速、 Heroku へプッシュしてみます。

$ git push heroku master
Counting objects: 9, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 828 bytes | 0 bytes/s, done.
Total 6 (delta 4), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Ruby app detected
remote: -----> Compiling Ruby/Rails
remote: -----> Using Ruby version: ruby-2.3.0
remote: ###### WARNING:
remote:        You have the `.bundle/config` file checked into your repository
remote:        It contains local state like the location of the installed bundle
remote:        as well as configured git local gems, and other settings that should
remote:        not be shared between multiple checkouts of a single repo. Please
remote:        remove the `.bundle/` folder from your repo and add it to your `.gitignore` file.
remote:        https://devcenter.heroku.com/articles/bundler-configuration
remote:
remote: -----> Installing dependencies using bundler 1.11.2
remote:        Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment
remote:        Fetching gem metadata from https://rubygems.org/..........
remote:        Fetching version metadata from https://rubygems.org/...
remote:        Fetching dependency metadata from https://rubygems.org/..
remote:        Installing rake 11.2.2
remote:        Installing concurrent-ruby 1.0.2
remote:        Installing i18n 0.7.0
remote:        Installing thread_safe 0.3.5
remote:        Installing minitest 5.9.0
remote:        Installing builder 3.2.2
remote:        Installing erubis 2.7.0
remote:        Installing mini_portile2 2.1.0
remote:        Installing pkg-config 1.1.7
remote:        Installing nio4r 1.2.1 with native extensions
remote:        Installing rack 2.0.1
remote:        Installing websocket-extensions 0.1.2
remote:        Installing arel 7.0.0
remote:        Installing mime-types-data 3.2016.0521
remote:        Installing method_source 0.8.2
remote:        Using bundler 1.11.2
remote:        Installing puma 3.4.0 with native extensions
remote:        Installing thor 0.19.1
remote:        Installing tzinfo 1.2.2
remote:        Installing nokogiri 1.6.8 with native extensions
remote:        Installing websocket-driver 0.6.4 with native extensions
remote:        Installing rack-test 0.6.3
remote:        Installing sprockets 3.6.3
remote:        Installing mime-types 3.1
remote:        Installing activesupport 5.0.0
remote:        Installing mail 2.6.4
remote:        Installing globalid 0.3.6
remote:        Installing activemodel 5.0.0
remote:        Installing activejob 5.0.0
remote:        Installing activerecord 5.0.0
remote:        Installing rails-dom-testing 2.0.1
remote:        Installing loofah 2.0.3
remote:        Installing rails-html-sanitizer 1.0.3
remote:        Installing actionview 5.0.0
remote:        Installing actionpack 5.0.0
remote:        Installing actionmailer 5.0.0
remote:        Installing actioncable 5.0.0
remote:        Installing railties 5.0.0
remote:        Installing sprockets-rails 3.1.1
remote:        Installing rails 5.0.0
remote:        Installing pg 0.18.4 with native extensions                                                                           
remote:        Bundle complete! 9 Gemfile dependencies, 41 gems now installed. 
remote:        Gems in the groups development and test were not installed.
remote:        Bundled gems are installed into ./vendor/bundle.
remote:        Bundle completed (19.95s)
remote:        Cleaning up the bundler cache.
remote:
remote: ###### WARNING:
remote:        You have the `.bundle/config` file checked into your repository
remote:        It contains local state like the location of the installed bundle
remote:        as well as configured git local gems, and other settings that should
remote:        not be shared between multiple checkouts of a single repo. Please
remote:        remove the `.bundle/` folder from your repo and add it to your `.gitignore` file.
remote:        https://devcenter.heroku.com/articles/bundler-configuration
remote:
remote: ###### WARNING:
remote:        No Procfile detected, using the default web server.
remote:        We recommend explicitly declaring how to boot your server process via a Procfile.
remote:        https://devcenter.heroku.com/articles/ruby-default-web-server
remote:
remote: -----> Discovering process types
remote:        Procfile declares types     -> (none)
remote:        Default types for buildpack -> console, rake, web, worker
remote:
remote: -----> Compressing...
remote:        Done: 23.1M
remote: -----> Launching...
remote:        Released v6
remote:        https://XXXXX-YYYYY-12345.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/XXXXX-YYYYY-12345.git
 * [new branch]      master -> master

途中で、 sqlite3.h is missing みたいなメッセージが出たり、 「詳しくは https://devcenter.heroku.com/articles/sqlite3 を見てね」的なメッセージが出たなら、 Gemfilegroup :development の中に gem 'sqlite' を押し込めましょう。

Gemfile
group :development do
  # Use sqlite3 as the database for Active Record
  gem 'sqlite3'
end

必要に応じて、DBのマイグレーションを行います。

$ heroku run rake db:migrate
Running rake db:migrate on ⬢ XXXXX-YYYYY-12345... up, run.2785                                                               
D, [2016-07-12T16:25:40.173919 #3] DEBUG -- :    (11.2ms)  CREATE TABLE "schema_migrations" ("version" character varying PRIMARY KEY)
D, [2016-07-12T16:25:40.187941 #3] DEBUG -- :    (9.3ms)  CREATE TABLE "ar_internal_metadata" ("key" character varying PRIMARY KEY, "value" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
D, [2016-07-12T16:25:40.190308 #3] DEBUG -- :    (1.0ms)  SELECT pg_try_advisory_lock(1753797496500759360);
D, [2016-07-12T16:25:40.200901 #3] DEBUG -- :   ActiveRecord::SchemaMigration Load (1.1ms)  SELECT "schema_migrations".* FROM "schema_migrations"
I, [2016-07-12T16:25:40.206248 #3]  INFO -- : Migrating to CreatePosts (20160710102422)
D, [2016-07-12T16:25:40.208344 #3] DEBUG -- :    (0.7ms)  BEGIN
== 20160710102422 CreatePosts: migrating ======================================
-- create_table(:posts)
D, [2016-07-12T16:25:40.216973 #3] DEBUG -- :    (7.4ms)  CREATE TABLE "posts" ("id" serial primary key, "title" character varying, "url" character varying, "comment" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
   -> 0.0085s
== 20160710102422 CreatePosts: migrated (0.0087s) =============================

D, [2016-07-12T16:25:40.224358 #3] DEBUG -- :   SQL (1.1ms)  INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version"  [["version", "20160710102422"]]
D, [2016-07-12T16:25:40.227280 #3] DEBUG -- :    (2.6ms)  COMMIT
I, [2016-07-12T16:25:40.227414 #3]  INFO -- : Migrating to AddDateToPost (20160710152551)
D, [2016-07-12T16:25:40.228671 #3] DEBUG -- :    (0.7ms)  BEGIN
== 20160710152551 AddDateToPost: migrating ====================================
-- add_column(:posts, :date, :datetime)
D, [2016-07-12T16:25:40.230074 #3] DEBUG -- :    (1.0ms)  ALTER TABLE "posts" ADD "date" timestamp
   -> 0.0013s
== 20160710152551 AddDateToPost: migrated (0.0014s) ===========================

D, [2016-07-12T16:25:40.231584 #3] DEBUG -- :   SQL (0.8ms)  INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version"  [["version", "20160710152551"]]
D, [2016-07-12T16:25:40.233287 #3] DEBUG -- :    (1.5ms)  COMMIT
D, [2016-07-12T16:25:40.240319 #3] DEBUG -- :   ActiveRecord::InternalMetadata Load (0.9ms)  SELECT  "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1 LIMIT $2  [["key", :environment], ["LIMIT", 1]]
D, [2016-07-12T16:25:40.248994 #3] DEBUG -- :    (0.7ms)  BEGIN
D, [2016-07-12T16:25:40.251805 #3] DEBUG -- :   SQL (1.0ms)  INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "key"  [["key", "environment"], ["value", "production"], ["created_at", 2016-07-12 16:25:40 +0000], ["updated_at", 2016-07-12 16:25:40 +0000]]
D, [2016-07-12T16:25:40.253633 #3] DEBUG -- :    (1.5ms)  COMMIT
D, [2016-07-12T16:25:40.254643 #3] DEBUG -- :    (0.8ms)  SELECT pg_advisory_unlock(1753797496500759360)

これでおしまい。うまくいっていれば、ログ中に出てきたhttp://~.herokuapp.comでアクセスできる。

デバッグ

プロセス状態

heroku ps で現在の状態を見ることができる。

$ heroku ps
Free dyno hours quota remaining this month: 1000h 0m (100%)
For more information on dyno sleeping and how to upgrade, see:
https://devcenter.heroku.com/articles/dyno-sleeping

=== web (Free): bin/rails server -p $PORT -e $RAILS_ENV (1)
web.1: up 2016/07/13 01:25:02 +0900 (~ 2m ago)

ログ

ログを見るなら heroku logs--tail オプションを付けると、リアルタイムで見られる。

$ heroku logs
$ heroku logs --tail

環境変数

# 環境変数の一覧
$ heroku config
=== XXXXX-YYYYY-12345 Config Vars
DATABASE_URL:             postgres://hogehogehoge:foobarbaz@ec2-NNN-NNN-NNN-NNN.compute-M.amazonaws.com:PPPP/fugapiyo
LANG:                     en_US.UTF-8
RACK_ENV:                 production
RAILS_ENV:                production
RAILS_LOG_TO_STDOUT:      enabled
RAILS_SERVE_STATIC_FILES: enabled
SECRET_KEY_BASE:          foobarbazhogefugapiyo
# 環境変数のうち、指定したものだけを表示
$ heroku config:get LANG                                                              
en_US.UTF-8
# 環境変数をセット
$ heroku config:set SECRET_KEY_BASE=`rake secret`                                     
Setting SECRET_KEY_BASE and restarting ⬢ XXXXX-YYYYY-12345... done, v8                                                       
SECRET_KEY_BASE: hogefugapiyofoobarbaz

コンソール

$ heroku run rails console
Running rails console on ⬢ XXXXX-YYYYY-12345... up, run.4519
Loading production environment (Rails 5.0.0)
irb(main):001:0> 

サーバの再起動

$ heroku restart
Restarting dynos on ⬢ XXXXX-YYYYY-12345... done

Heroku 無料枠の範囲

1つのサーバプロセスを立ち上げると、 1 dyno を使用するということになります。 1 dyno を1時間使用すると、 1 dyno hour を消費したことになります。

各アカウントに対し 550 dyno hours を、有効なクレジットカードを heroku に登録していれば、さらに 450 dyno hours(計 1000 dyno hours) を一月に付与されます。

31日間の可動に必要な dyno hours は単純計算で 744 dyno hours (= 24 hours * 31 days) ですが、 heroku run consoleheroku run rake db:migrate などのコマンドを実行する One-off Dyno と呼ばれる Dyno の実行も、利用量に含まれるので注意。

以前は「18時間稼働&6時間スリープ」のような制限がありましたが、今は上記の制限に代わりました。

参考

44
41
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
44
41