Rails
Heroku
npm
PostGIS

Herokuの操作覚書(Railsを中心に)

0. はじめに

仕事でherokuを使うことは全くないのですが、プライベートで作ったリポジトリを外部に公開するときは、Railsプロジェクトであればherokuを使うのはとても手っ取り早い良い方法だと思います。
仕事で使っていない以上、年に数回しかherokuに触ることなく、その度ごとにheroku固有のやり方やコマンドを忘れてしまうので、まとめていきたいと思います。
逐次追記する予定です。

1. herokuでRailsを使いつつ、デプロイ時にトランスパイルする

私が作るRailsプロジェクトの多くは、frontendディレクトリを持ち、その中はfrontendの世界観で構成されており、webpackを使ってbabel等でトランスパイルしたファイルをapp/assets配下に吐き出し、sproketsで呼び出すというやり方をすることが多いです。
この辺りは以前一緒に働いていた方のこちらの記事をご参照ください。

仕事では、様々な事情から、トランスパイルしたファイルをgitに追加して運用しているのですが、自動生成されたファイルをcommitするのはよろしくないという思いがあるので、プライベートで作っているプロジェクトでは、トランスパイルしたファイルはcommitに含めていません。
当然ながら、.gitignoreにはapp/assets配下は除くように設定してあります。

.gitignore
/app/assets/javascripts/*

このような状況の中で、herokuにdeploy時にwebpackのコマンドも実行してあげる方法を記述します。

今回のRailsプロジェクトのディレクトリ構成は、

.
├── Gemfile
├── (省略)
├── app
├── frontend
│   └── package.json -> ../package.json (symbolic link)
└─ package.json

となっており、普段は、frontendディレクトリ下でnpm run watchyarn watchを実行して開発を行うことが多いです。
package.jsonは当初は、frontend配下に置いていたのですが、herokuのnodeのbuildpacksではリポジトリ直下のpackage.jsonを見に行くようなので、リポジトリ直下にpackage.jsonを置き、frontendディレクトリ直下にはリポジトリ直下のpackage.jsonに対してシンボリックリンクを貼るような形にしています。

デプロイ後にnpm run releaseを実行するために、package.jsonのheroku-postbuildを追加します。このスクリプトは、herokuのbuildpacks(後述)のnodejsのところで実行されます。cd ../コマンドなどはもしかしたら不要かもしれません。

"scripts": {
  "release": "webpack --mode production --config webpack.config.js",
  "watch": "webpack --mode development --watch --config webpack.config.js",
  "heroku-postbuild": "cd frontend; npm run release; cd ../"
}

herokuには、buildpacksというものがあり、rubyを選んだ場合は、rubyしかないはずです。heroku buildpacksコマンドで確認できます。

$ heroku buildpacks
=== your-app-name Buildpack URLs
1. heroku/ruby

今回はnode.jsも使用したいため、buildpackを追加します。

heroku buildpacks:add --index 1 https://github.com/heroku/heroku-buildpack-nodejs

ここで注意は、--index 1とすることです。これを忘れると、デプロイ後、アクセス時にnpm startが走ってしまい、エラーとなります。
このコマンド実行後のbuildpacksは以下のようになると思います。

$ heroku buildpacks
=== your-app-name Buildpack URLs
1. https://github.com/heroku/heroku-buildpack-nodejs
2. heroku/ruby

これで通常通りgit push heroku masterなどとすればdeploy時にまずnpm run releaseコマンドが走り、app/assets配下にファイルを置いてくれます。
その後、railsのdeployが始まり、その中で、assets:precompileが行われ、ここから先はsproketsの世界になります。
sproketsが嫌な方はuglifyやダイジェストの付与等もwebpackにやってもらうような設定にしても良いかと思います。

2. postgisを入れる。

地理除法をPostgreSQL上で扱うために使われるのがpostgisです。これのheroku上での利用方法について記載します。
まずは、buildpackを追加します。

heroku buildpacks:add --index 2 https://github.com/cyberdelia/heroku-geo-buildpack.giat

herokuのpostgresqlに接続(接続方法は下記の「よく使うコマンド」参照)し、EXTENSIONを作成します。

CREATE EXTENSION postgis;

このままだと、migrationする際に怒られます。

undefined method `st_point' for #<ActiveRecord::ConnectionAdapters::PostgreSQL::TableDefinition:0x00000004ab9ab0>

herokuの中の環境変数のDATABASE_URLを書き換える必要があります。(参照

database.yml
default: &default
  adapter: postgis

production:
  <<: *default
  url: <%= ENV.fetch('DATABASE_URL', '').sub(/^postgres/, "postgis") %>

最後にmigrationの実行しカラムを追加します。

heroku run rake db:migrate

2. postgresqlのデータをバックアップする

完全にコマンドのメモです。

既存のバックアップファイルの確認。バックアップを一度も実行したことない場合はNo backups found.などと出るはずです。

$ heroku pg:backups --app your-app-name
# --app your-app-name は -a your-app-name と同じ意味。

=== Backups
ID    Created at                 Status                               Size     Database
────  ─────────────────────────  ───────────────────────────────────  ───────  ────────
b002  2018-03-10 14:22:16 +0000  Completed 2018-03-10 14:22:17 +0000  39.41kB  DATABASE
b001  2018-03-09 15:26:41 +0000  Completed 2018-03-09 15:26:42 +0000  34.71kB  DATABASE

=== Restores
No restores found. Use heroku pg:backups:restore to restore a backup

=== Copies
No copies found. Use heroku pg:copy to copy a database to another

バックアップを行います。

$ heroku pg:backups:capture --app your-app-name

Starting backup of postgresql-pointy-60299... done

Use Ctrl-C at any time to stop monitoring progress; the backup will continue running.
Use heroku pg:backups:info to check progress.
Stop a running backup with heroku pg:backups:cancel.

Backing up DATABASE to b001... done

これを行なった後、再度heroku pg:backups --app your-app-nameを実行すれば、Backupsのところに表示されるはずです。IDのところが大事です。

バックアップファイルをlocalに持ってくる方法になります。Macユーザーでcurlが入っていない場合は、homebrewなどでinstallしてください。publick-urlのあとのb001の箇所は前述のIDのところ値を入れます。

$ curl -o `date "+%Y%m%d%H%M%S"`.dump $(heroku pg:backups public-url b001 --app your-app-name)

バックアップしたファイルでlocalのpostgresqlにリストアします。ファイル名はcurlしたときに保存されたファイル名を指定します。

$ pg_restore --verbose --clean --no-acl --no-owner -h localhost -d your_database_name 20180101000000.dump

よく使うコマンド

  • sshする
$ heroku run bash
  • 直接rails consoleに行きたい場合
$ heroku run console
  • migrationを実行する
heroku run rake db:migrate
  • databaseに接続したい場合
$ heroku run console

でrails consoleに入り、

config = ActiveRecord::Base.configurations[Rails.env] || Rails.application.config.database_configuration[Rails.env]

にて、passwordを調べる。

$ heroku run bash
$ rails db
Password: # ↑で調べたpasswordを入力