buildpack:linuxbrewを使ってmecab入りRails環境をHerokuに作る

したいこと
---

* mecab入りのrails環境をHerokuに作りたい
* [heroku-buildpack-mecab](https://github.com/diasks2/heroku-buildpack-mecab)というのもあったけど今後gslとか、他のネイティブライブラリを使う予定があるのでもう少し汎用的な仕組みを使いたい

heroku-buildpack-linuxbrew
---

* [heroku-buildpack-linuxbrew](https://github.com/sunny4381/heroku-buildpack-linuxbrew)というbuildpackが公開されてた
* そもそも[linuxbrew](http://linuxbrew.sh/)というMacのbrewをforkしてlinuxで動くようにしたパッケージマネージャがあって、root権限なしでホームディレクトリに各種パッケージをインストールすることができる
* 上記buildpackはlinuxbrewの仕組みでパッケージをherokuにインストールしてくれる

インストール手順
---

結構手こずったのでメモっておきます。

### 環境変数、ビルドパックの設定
Herokuの環境変数とビルドパックの設定をします。

```:bash
heroku buildpacks:set https://github.com/heroku/heroku-buildpack-multi
heroku config:add LD_LIBRARY_PATH=/app/.linuxbrew/lib
heroku config:set MECAB_PATH=/app/.linuxbrew/lib/libmecab.so
```

ポイントは下記です。

* ビルドパックの指定では ``` heroku buildpacks:set ```を使う
  * 古いドキュメントだとここが ``` heroku config:set ```を使うことになっているが、最近はHerokuの仕様変更によりこの方法でないと動かない
* ここのビルドパック指定ではlinuxbrewではなく、[heroku-buildpack-multi](https://github.com/heroku/heroku-buildpack-multi)を指定する
  * 後でファイルで複数のビルドパックを指定するため
* soライブラリは```/app/.linuxbrew/lib```下にある前提で指定する

### 設定ファイルの作成
2つの設定ファイルをリポジトリルートの下に作成します。

```:.cellar
mecab
mecab-ipadic
```

```:.buildpacks
https://github.com/sunny4381/heroku-buildpack-linuxbrew.git
https://github.com/heroku/heroku-buildpack-ruby
```

* .cellarにはインストールしたいlinuxbrewのパッケージ名を記入しておく
* .buildpacksに、heroku-buildpack-linuxbrewと、アプリケーション側で使いたいビルドパックを指定しておく
  * 今回はrailsアプリなので、heroku-buildpack-rubyを指定

### デプロイ
普通に git pushします。

```:bash
$ git push heroku master
Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (5/5), 562 bytes | 0 bytes/s, done.
Total 5 (delta 3), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Fetching set buildpack https://github.com/heroku/heroku-buildpack-multi... done
remote: -----> Multipack app detected
remote: =====> Downloading Buildpack: https://github.com/sunny4381/heroku-buildpack-linuxbrew.git
remote: =====> Detected Framework: linuxbrew
remote: -----> Installing linuxbrew
remote:        Cloning into '/app/.linuxbrew'...
remote:        export PATH="$HOME/.linuxbrew/bin:$PATH"
remote:        export MANPATH="$HOME/.linuxbrew/share/man:$MANPATH"
remote:        export INFOPATH="$HOME/.linuxbrew/share/info:$INFOPATH"
remote:        export LD_LIBRARY_PATH="$HOME/.linuxbrew/lib:$LD_LIBRARY_PATH"
remote: -----> Installing mecab using brew
remote:        ==> Downloading https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7cENtOXlicTFaRUE
remote:        ==> Downloading from https://doc-0c-74-docs.googleusercontent.com/docs/securesc/ha0ro937gcuc7l7deffksulhg5h7mbp1/eg9sju51j7chcbpq3jt6fs3dbftijq7f/1462327200000/13553212398903315502/*/0B4y35FiV1wh7cENtOXlicTFaRUE?e=download
remote:        ==> ./configure --prefix=/app/.linuxbrew/Cellar/mecab/0.996 --sysconfdir=/app/.linuxbrew/etc
remote:        ==> make install
remote:        /app/.linuxbrew/Cellar/mecab/0.996: 19 files, 4.8M, built in 1 minute
remote: -----> Installing mecab-ipadic using brew
remote:        ==> Downloading https://downloads.sourceforge.net/project/mecab/mecab-ipadic/2.7.0-20070801/mecab-ipadic-2.7.0-20070801.tar.gz
remote:        ==> Downloading from http://iweb.dl.sourceforge.net/project/mecab/mecab-ipadic/2.7.0-20070801/mecab-ipadic-2.7.0-20070801.tar.gz
remote:        ==> ./configure --prefix=/app/.linuxbrew/Cellar/mecab-ipadic/2.7.0-20070801 --with-charset=utf8 --with-dicdir=/app/.linuxbrew/Cellar/mecab-ipadic/2.7.0-20070801/lib/mecab/dic/ipadic
remote:        ==> make install
remote:        ==> Caveats
remote:        To enable mecab-ipadic dictionary, add to /app/.linuxbrew/etc/mecabrc:
remote:          dicdir = /app/.linuxbrew/lib/mecab/dic/ipadic
remote:        
remote:        ==> Summary
remote:        /app/.linuxbrew/Cellar/mecab-ipadic/2.7.0-20070801: 15 files, 50.6M, built in 28 seconds
remote: =====> Downloading Buildpack: https://github.com/heroku/heroku-buildpack-ruby
remote: =====> Detected Framework: Ruby
remote: -----> Compiling Ruby/Rails
remote: -----> Using Ruby version: ruby-2.2.4
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:        Warning: the running version of Bundler is older than the version that created the lockfile. We suggest you upgrade to the latest version of Bundler by running `gem install bundler`.
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:        Using concurrent-ruby 1.0.1
remote:        Using rake 11.1.1
remote:        Using i18n 0.7.0
remote:        Using minitest 5.8.4
remote:        Using thread_safe 0.3.5
remote:        Using builder 3.2.2
remote:        Using erubis 2.7.0
remote:        Using mini_portile2 2.0.0
remote:        Using json 1.8.3
remote:        Using nio4r 1.2.1
remote:        Using websocket-extensions 0.1.2
remote:        Using mime-types 2.99.1
remote:        Using arel 7.0.0
remote:        Using fast-stemmer 1.0.2
remote:        Using coffee-script-source 1.10.0
remote:        Using execjs 2.6.0
remote:        Using method_source 0.8.2
remote:        Using thor 0.19.1
remote:        Using commonjs 0.2.7
remote:        Using ffi 1.9.10
remote:        Using hkdf 0.2.0
remote:        Using multi_json 1.11.2
remote:        Using tilt 2.0.2
remote:        Using libv8 3.16.14.13
remote:        Using pg 0.18.4
remote:        Using puma 3.2.0
remote:        Using bundler 1.11.2
remote:        Using redis 3.2.2
remote:        Using ref 2.0.0
remote:        Using sass 3.4.21
remote:        Using underscore-rails 1.8.3
remote:        Using tzinfo 1.2.2
remote:        Using nokogiri 1.6.7.2
remote:        Using rack 2.0.0.alpha
remote:        Using websocket-driver 0.6.3
remote:        Using mail 2.6.3
remote:        Using classifier 1.3.4
remote:        Using coffee-script 2.4.1
remote:        Using uglifier 2.7.2
remote:        Using less 2.6.0
remote:        Using natto 1.1.0
remote:        Using webpush 0.1.4 from https://github.com/shouta-dev/webpush.git (at master@10c63f6)
remote:        Using therubyracer 0.12.2
remote:        Using activesupport 5.0.0.beta3
remote:        Using loofah 2.0.3
remote:        Using rack-test 0.6.3
remote:        Using sprockets 3.5.2
remote:        Using rails-deprecated_sanitizer 1.0.3
remote:        Using globalid 0.3.6
remote:        Using activemodel 5.0.0.beta3
remote:        Using jbuilder 2.4.1
remote:        Using rails-html-sanitizer 1.0.3
remote:        Using rails-dom-testing 1.0.7
remote:        Using activejob 5.0.0.beta3
remote:        Using activerecord 5.0.0.beta3
remote:        Using actionview 5.0.0.beta3
remote:        Using actionpack 5.0.0.beta3
remote:        Using actioncable 5.0.0.beta3
remote:        Using actionmailer 5.0.0.beta3
remote:        Using railties 5.0.0.beta3
remote:        Using less-rails 2.7.1
remote:        Using sprockets-rails 3.0.4
remote:        Using coffee-rails 4.1.1
remote:        Using jquery-rails 4.1.1
remote:        Using toastr-rails 1.0.3
remote:        Using twitter-bootstrap-rails 3.2.2
remote:        Using rails 5.0.0.beta3
remote:        Using sass-rails 5.0.4
remote:        Installing foreman 0.81.0
remote:        Bundle complete! 25 Gemfile dependencies, 69 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 (3.55s)
remote:        Cleaning up the bundler cache.
remote:        Warning: the running version of Bundler is older than the version that created the lockfile. We suggest you upgrade to the latest version of Bundler by running `gem install bundler`.
remote: -----> Preparing app for Rails asset pipeline
remote:        Running: rake assets:precompile
remote:        Notice: for 10x faster LSI support, please install http://rb-gsl.rubyforge.org/
remote:        Asset precompilation completed (2.23s)
remote:        Cleaning assets
remote:        Running: rake assets:clean
remote:        Notice: for 10x faster LSI support, please install http://rb-gsl.rubyforge.org/
remote: 
remote: ###### WARNING:
remote:        You have not declared a Ruby version in your Gemfile.
remote:        To set your Ruby version add this line to your Gemfile:
remote:        ruby '2.2.4'
remote:        # See https://devcenter.heroku.com/articles/ruby-versions for more information.
remote: 
remote: Using release configuration from last framework (Ruby).
remote: 
remote: -----> Discovering process types
remote:        Procfile declares types     -> web
remote:        Default types for buildpack -> console, rake, worker
remote: 
remote: -----> Compressing...
remote:        Done: 144.8M
remote: -----> Launching...
remote:        Released v59
remote:        https://example.herokuapp.com/ deployed to Heroku
remote: 
remote: Verifying deploy... done.
To https://git.heroku.com/example.git
   0000000..0000001  master -> master
```

見所としては下記でしょうか。

* 1つめのbuildpackでlinuxbrew経由でmecabが入ってきている
  * ちょっと時間がかかる
* 2つめのbuildpackでrailsアプリが普通にインストールされている
  * ```natto```というライブラリがmecab依存

### プロセス数の追加
このままだとなぜかdyno数が0になっていてアクセスできなかったので下記で増やします。

```:bash
$ heroku ps:scale web=1
```

終わりに
---

これ使えばネイティブライブラリが必要なアプリはほとんどHerokuで動くようになりそうです。各種ビルドパックやパッケージを公開してくれている作者様に感謝。