Rails の開発環境をサクッ構築するために heroku を使ったときのメモ.

環境

  • Rails 5.1.6
  • Ruby 2.4.x
  • MySQL
  • Webpacker つかう

Heroku CLI

$ brew install heroku

# if already installed
$ brew upgrade heroku

$ brew -v

Heroku 設定

  • herokuでアプリケーション作成
  • クレカ登録(後述の MySQL 向けプラグインを追加するために必要.Free プランを選べば課金はされない)
  • プラグイン追加
    • Configure Add-ons
    • 「Clear DB」で検索して選択 -> Provision

heroku-clear-db.png

Login

heroku に登録している email, password でログインする.

$ heroku login

DB のセットアップ

先述の ClearDB をプラグインとして追加しているとそれ用の環境変数が設定される.

$ heroku config -a <your-app-name>
=== your-app-name Config Vars
CLEARDB_DATABASE_URL: mysql://xxxxxxxxxxxxxx:xxxxxxxxxx@xxxxxxxxxxxxxxxx.cleardb.net/heroku_xxxxxxxxxxxx?reconnect=true

mysql の箇所を mysql2 に変更して別名で登録する

$ heroku config:set DATABASE_URL=mysql://xxxxxxxxxxxxxx:xxxxxxxxxx@xxxxxxxxxxxxxxxx.cleardb.net/heroku_xxxxxxxxxxxx?reconnect=true -a <your-app-name>
Setting DATABASE_URL and restarting ⬢ your-app-name... done, v4

設定した DATABASE_URL を接続情報として設定する.ClearDB の場合 url に先程の値を設定するだけでよい.

# config/database.sample.yml

production:
  # For Heroku
  url: <%= ENV['DATABASE_URL'] %>

環境変数

その他,必要な環境変数を設定する.

$ heroku config:set XXXXXX=xxxxxx

デプロイ

一旦デプロイしてみる.

$ git remote -v

heroku が Remote Repository に登録されていない場合は追加する

$ heroku git:remote -a your-app-name

デプロイ実行.

$ git push heroku master

$ git push heroku master
Enumerating objects: 750, done.
Counting objects: 100% (750/750), done.
Delta compression using up to 8 threads.
Compressing objects: 100% (469/469), done.
Writing objects: 100% (750/750), 163.13 KiB | 8.58 MiB/s, done.
Total 750 (delta 347), reused 529 (delta 223)
remote: Compressing source files... done.
remote: Building source:

••• (中略)

remote: -----> Detecting rake tasks
remote: -----> Preparing app for Rails asset pipeline
remote:        Running: rake assets:precompile
remote:        yarn install v1.5.1
remote:        [1/5] Validating package.json...
remote:        error mixed-nuts@: The engine "node" is incompatible with this module. Expected version "8.11.3".
remote:        error An unexpected error occurred: "Found incompatible module".
remote:        info If you think this is a bug, please open a bug report with the information provided in "/tmp/build_b49b2f88d5ea1e404f425db2d2a8bf55/yarn-error.log".
remote:        info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
remote:        I, [2018-07-19T02:14:37.162948 #1621]  INFO -- : Writing /tmp/build_b49b2f88d5ea1e404f425db2d2a8bf55/public/assets/application-2b0484413e031f2b6ab1e6b1ff622e8c65bf0c834557595a5bf6361807ca24d4.js
remote:        I, [2018-07-19T02:14:37.163879 #1621]  INFO -- : Writing /tmp/build_b49b2f88d5ea1e404f425db2d2a8bf55/public/assets/application-2b0484413e031f2b6ab1e6b1ff622e8c65bf0c834557595a5bf6361807ca24d4.js.gz
remote:        I, [2018-07-19T02:14:37.171636 #1621]  INFO -- : Writing /tmp/build_b49b2f88d5ea1e404f425db2d2a8bf55/public/assets/application-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css
remote:        I, [2018-07-19T02:14:37.172018 #1621]  INFO -- : Writing /tmp/build_b49b2f88d5ea1e404f425db2d2a8bf55/public/assets/application-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css.gz
remote:        Webpacker is installed 🎉 🍰
remote:        Using /tmp/build_b49b2f88d5ea1e404f425db2d2a8bf55/config/webpacker.yml file for setting up webpack paths
remote:        Compiling…
remote:        Compilation failed:
remote:        
remote:        /tmp/build_b49b2f88d5ea1e404f425db2d2a8bf55/vendor/bundle/ruby/2.4.0/gems/webpacker-3.4.1/lib/webpacker/webpack_runner.rb:11:in `exec': No such file or directory - /tmp/build_b49b2f88d5ea1e404f425db2d2a8bf55/node_modules/.bin/webpack (Errno::ENOENT)
remote:         from /tmp/build_b49b2f88d5ea1e404f425db2d2a8bf55/vendor/bundle/ruby/2.4.0/gems/webpacker-3.4.1/lib/webpacker/webpack_runner.rb:11:in `block in run'
remote:         from /tmp/build_b49b2f88d5ea1e404f425db2d2a8bf55/vendor/bundle/ruby/2.4.0/gems/webpacker-3.4.1/lib/webpacker/webpack_runner.rb:10:in `chdir'
remote:         from /tmp/build_b49b2f88d5ea1e404f425db2d2a8bf55/vendor/bundle/ruby/2.4.0/gems/webpacker-3.4.1/lib/webpacker/webpack_runner.rb:10:in `run'
remote:         from /tmp/build_b49b2f88d5ea1e404f425db2d2a8bf55/vendor/bundle/ruby/2.4.0/gems/webpacker-3.4.1/lib/webpacker/runner.rb:6:in `run'
remote:         from ./bin/webpack:15:in `<main>'
remote:        
remote:
remote:  !
remote:  !     Precompiling assets failed.
remote:  !
remote:  !     Push rejected, failed to compile Ruby app.
remote: 
remote:  !     Push failed
remote: Verifying deploy...
remote: 
remote: !       Push rejected to your-app-name.
remote:

webpacker 周りのエラー

どうやら,デフォルトの buildpacks が古いらしい

buildpacksを設定し直す.buildpacks:set buildpacks:add は異なるので注意.

$ heroku buildpacks:set heroku/nodejs
Buildpack set. Next release on your-app-name will use heroku/nodejs.
Run git push heroku master to create a new release using this buildpack.
$ heroku buildpacks
=== your-app-name Buildpack URL
heroku/nodejs
$ heroku buildpacks:add heroku/ruby
Buildpack added. Next release on your-app-name will use:
  1. heroku/nodejs
  2. heroku/ruby
Run git push heroku master to create a new release using these buildpacks.
$ heroku buildpacks
=== your-app-name Buildpack URLs
  1. heroku/nodejs
  2. heroku/ruby

Sprockets 周りのエラー

remote:  !
remote:  !     A security vulnerability has been detected in your application.
remote:  !     To protect your application you must take action. Your application
remote:  !     is currently exposing its credentials via an easy to exploit directory
remote:  !     traversal.
remote:  !
remote:  !     To protect your application you must either upgrade to Sprockets version "3.7.2"
remote:  !     or disable dynamic compilation at runtime by setting:
remote:  !
remote:  !     ```
remote:  !     config.assets.compile = false # Disables security vulnerability
remote:  !     ```
remote:  !
remote:  !     To read more about this security vulnerability please refer to this blog post:
remote:  !     https://blog.heroku.com/rails-asset-pipeline-vulnerability
remote:  !

Rails Asset Pipeline Directory Traversal Vulnerability (CVE-2018-3760)

Directory Traversal 関連の脆弱性に関する指摘らしい. エラーメッセージに記載の通り sprockets を 3.7.2 にアップデートしたら解決した.

$ gem update sprockets

再デプロイ

$ git push heroku master
Enumerating objects: 750, done.
Counting objects: 100% (750/750), done.
Delta compression using up to 8 threads.
Compressing objects: 100% (469/469), done.
Writing objects: 100% (750/750), 163.13 KiB | 8.58 MiB/s, done.
Total 750 (delta 347), reused 529 (delta 223)
remote: Compressing source files... done.
remote: Building source:

••• (中略)

remote: -----> Discovering process types
remote:        Procfile declares types     -> (none)
remote:        Default types for buildpack -> console, rake, web, worker
remote: 
remote: -----> Compressing...
remote:        Done: 103.3M
remote: -----> Launching...
remote:        Released v6
remote:        https://your-app-name.herokuapp.com/ deployed to Heroku
remote: 
remote: Verifying deploy... done.
To https://git.heroku.com/your-app-name.git
 * [new branch]      master -> master

db:migrate

先程の設定でソースコードが配置されるので,database.sample.yml をコピーして,database.yml を設置する.

$ heroku run cp config/database.sample.yml config/database.yml
$ heroku run rails db:migrate RAILS_ENV=production

もっといいやり方でやりたい…🤔

Basic 認証を設定

次のようなコードを追加して basic 認証を設定することができる. BASIC_AUTH_USER BASIC_AUTH_PASSheroku config:set コマンドで予め設定しておく.

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  http_basic_authenticate_with name: ENV['BASIC_AUTH_USER'], password: ENV['BASIC_AUTH_PASS'] if Rails.env == "production"
end

master ブランチ以外をデプロイ

次のように suffix に :master つけるとそのブランチがデプロイできる.

# develop ブランチが heroku/master としてデプロイされる
$ git push heroku devlop:master

まとめ

heroku 楽ちん😇👏✨