Heroku で Rails4 + MySQL を動かす

環境は Mac
Heroku に Rails4 + MySQL で動くアプリをデプロイする。
DB はデフォルトでは PostgreSQL が使われるが、 MySQL が使えるアドオンの「ClearDB」を導入する。

事前準備

Heroku アカウントは取得済み。

「heroku toolbelt」のインストール。homebrew で。

$ brew heroku-toolbelt

toolbelt のコマンドで Heroku にログイン。メールアドレスとパスワードで。

$ heroku login

SSH 公開鍵の登録

認証用の鍵を作成する。Heroku 用としてファイル名heroku_id_rsaで作成。

$ cd ~/.ssh
$ ssh-keygen -f heroku_id_rsa

~/.ssh/configに Heroku 用の設定を追加。

Host github.com
 User git
 port 22
 Hostname github.com
 IdentityFile ~/.ssh/github_id_rsa
 TCPKeepAlive yes
 IdentitiesOnly yes

Host heroku.com
 User git
 port 22
 Hostname heroku.com
 IdentityFile ~/.ssh/heroku_id_rsa
 TCPKeepAlive yes
 IdentitiesOnly yes

Heroku に公開鍵を登録する。

$ heroku keys:add ~/.ssh/heroku_id_rsa.pub

Uploading SSH public key /Users/xxx/.ssh/heroku_id_rsa.pub... done

確認

$ heroku keys

=== hoge@example.com Keys
ssh-rsa AAAAB8NzaC...DVj3R4Ww== hoge@mbp.local

登録した鍵を削除したい場合

# 個別に
$ heroku keys:remove hoge@mbp.local

# 全部
$ heroku keys:clear

Rails4 アプリ作成

まずはローカル環境で Rails アプリを作成する。DB は MySQL を指定する。
Bundler, Rails4 はインストール済み。

$ bundle exec rails new heroku_sample_app -d mysql -T --skip-bundle
$ cd heroku_sample_app

Gemfile 修正

source 'https://rubygems.org'
ruby '2.1.2' # Rubyのバージョン指定追加

gem 'rails', '4.1.6'
gem 'mysql2' # -d mysql 指定で追加される

# snip

gem 'rails_12factor', group: :production # 追加

gem インストール

$ bin/bundle install --path vendor/bundle --without production

scaffold コマンドでアプリの雛形を作成

$ bin/rails generate scaffold book isbn:string title:string price:integer publish:string published:date

config.time_zoneの設定

config/application.rb

    config.time_zone = 'Tokyo'

ルーティングに Root パスを追加

config/routes.rb

Rails.application.routes.draw do
  resources :books
  root to: 'books#index'
end

git リポジトリ作成

RAILS_ROOTで git リポジトリを作成して add, commit する

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

Heroku にアプリ作成

$ heroku create heroku-sample-app-20140929
Creating heroku-sample-app-20140929... done, stack is cedar
http://heroku-sample-app-20140929.herokuapp.com/ | git@heroku.com:heroku-sample-app-20140929.git
Git remote heroku added

RAILS_ROOTで上記コマンドを実行していれば heroku のリモートリポジトリが追加される

$ git remote -v
heroku  git@heroku.com:heroku-sample-app-20140929.git (fetch)
heroku  git@heroku.com:heroku-sample-app-20140929.git (push)

先に Heroku でアプリを作った場合は以下でリモートリポジトリ追加

$ git remote add heroku git@heroku.com:heroku-sample-app-20140929.git

Heroku に push する。push していないとアドオンの追加ができない。

$ git push heroku master

「ClearDB」アドオンの追加

$ heroku addons:add cleardb:ignite
Adding cleardb:ignite on heroku-sample-app-20140929... done, v7 (free)
Use `heroku addons:docs cleardb` to view documentation.

これだけでOK。

DB の接続設定を修正

Heroku ではconfig/databse.yml環境変数から自動で作成される。

Heroku の環境変数を確認

$ heroku config

=== heroku-sample-app-20140929 Config Vars
CLEARDB_DATABASE_URL:       mysql://<username>:<password>@<host>/<database>?reconnect=true
DATABASE_URL:               postgres://<username>:<password>@<host>:<port>/<database>
HEROKU_POSTGRESQL_TEAL_URL: postgres://<username>:<password>@<host>:<port>/<database>
LANG:                       en_US.UTF-8
RACK_ENV:                   production
RAILS_ENV:                  production
SECRET_KEY_BASE:            ...

DATABASE_URLpostgreSQL の接続設定になっているのでこれをCLEARDB_DATABASE_URLに設定されている MySQL の接続設定に変更する。
またmysql2ライブラリを使っているので先頭のmysql://mysql2://に修正する。

$ heroku config:set DATABASE_URL='mysql2://<username>:<password>@<host>/<database>?reconnect=true'

タイムゾーンと LANG の設定もしておく。

$ heroku config:add TZ=Asia/Tokyo
$ heroku config:add LANG=ja_JP.UTF-8

確認

$ heroku config

=== heroku-sample-app-20140929 Config Vars
CLEARDB_DATABASE_URL:       mysql://<username>:<password>@<host>/<database>?reconnect=true
DATABASE_URL:               mysql2://<username>:<password>@<host>/<database>?reconnect=true
HEROKU_POSTGRESQL_TEAL_URL: postgres://<username>:<password>@<host>:<port>/<database>
LANG:                       ja_JP.UTF-8
RACK_ENV:                   production
RAILS_ENV:                  production
SECRET_KEY_BASE:            ...
TZ:                         Asia/Tokyo

サーバ再起動

$ heroku restart

Restarting dynos... done

マイグレーション実行

$ heroku run rake db:migrate

Running `rake db:migrate` attached to terminal... up, run.5491
Migrating to CreateBooks (20140929083547)
== 20140929083547 CreateBooks: migrating ======================================
-- create_table(:books)
   -> 0.0076s
== 20140929083547 CreateBooks: migrated (0.0080s) =============================

アプリ動作確認

以下コマンドを叩くとブラウザでアプリのページを開いてくれる。

$ heroku open

Opening heroku-sample-app-20140929... done

URL
http://heroku-sample-app-20140929.herokuapp.com/

CRUD アプリが問題なく動けばOK。

Heroku のアプリ管理画面

https://dashboard-next.heroku.com/apps

その他 Heroku コマンド

サーバのログ確認

$ heroku logs

# tail で確認
$ heroku logs --tail
$ heroku logs -t

rails console に接続

$ heroku run console

ClearDB の MySQL にターミナルで直接接続する

ClearDB の MySQL に直接接続して先ほどブラウザから登録したデータが DB に入っていることを確認する。

環境変数CLEARDB_DATABASE_URLを確認

$ heroku config | grep CLEARDB_DATABASE_URL
CLEARDB_DATABASE_URL:       mysql://<username>:<password>@<host>/<database>?reconnect=true

上記設定値を元に接続

$ mysql -u <username> -p -h <host> <database>
Enter password: <password>

ClearDB(MySQL)の現時点のバージョン

Server version: 5.5.37-log MySQL Community Server (GPL)

データを見てみる

mysql> show databases;
+------------------------+
| Database               |
+------------------------+
| information_schema     |
| heroku_ace37dcd48a46e9 |
+------------------------+

mysql> show tables;
+----------------------------------+
| Tables_in_heroku_ace37dcd48a46e9 |
+----------------------------------+
| books                            |
| schema_migrations                |
+----------------------------------+

mysql> select * from books;
+----+----------------+----------------------------------+-------+-----------------+------------+---------------------+---------------------+
| id | isbn           | title                            | price | publish         | published  | created_at          | updated_at          |
+----+----------------+----------------------------------+-------+-----------------+------------+---------------------+---------------------+
|  1 | 978-4774165165 | パーフェクト Ruby on Rails       |  3110 | 技術評論社      | 2014-06-06 | 2014-09-29 10:10:22 | 2014-09-29 10:10:40 |
+----+----------------+----------------------------------+-------+-----------------+------------+---------------------+---------------------+

mysql> show variables like '%time_zone';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone | UTC    |
| time_zone        | SYSTEM |
+------------------+--------+

データが MySQL に入っていることが確認できた。
注意すべき点として ClearDB の MySQLタイムゾーンUTC になっているので Railsconfig.active_record.default_timezoneもこれに合わせて UTC にしておくこと。設定しなければデフォルトで UTC になるので問題ない。
ただ、ローカル環境の MySQLタイムゾーンJSTconfig.active_record.default_timezone = :localを設定してるケースがあると思うので、その場合は config/application.rbではなくconfig/environments/development.rbに設定して production では何も設定しないようにして UTC になるようにしておく。

また、ClearDB では auto_increment のキーが1, 11, 21, 31,...と10づつ増えていくような設定になっているので注意。

ClearDB Developer Center - Frequently Asked Questions
http://www.cleardb.com/developers/help/faq#general_16


参考:

Getting Started with Rails 4.x on Heroku | Heroku Dev Center
https://devcenter.heroku.com/articles/getting-started-with-rails4

Managing Your SSH Keys | Heroku Dev Center
https://devcenter.heroku.com/articles/keys

ClearDB MySQL Database | Heroku Dev Center
https://devcenter.heroku.com/articles/cleardb