Heroku用Groongaのビルド方法 - 2014-06-05 - ククログ

ククログ

株式会社クリアコード > ククログ > Heroku用Groongaのビルド方法

Heroku用Groongaのビルド方法

HerokuにGroongaはインストールされていないので、HerokuでGroongaを使うためにはGroongaをビルドしなければいけません。今回はHerokuでGroongaをビルドする方法を説明します。

buildpack

Herokuにインストールされていないソフトウェアを使えるようにする仕組みがbuildpackです。GroongaはHerokuにインストールされていないソフトウェアなので、buildpackの仕組みに従う必要があります。

buildpackの作り方

buildpackの仕組みに従うには次の作業が必要です。

  1. Heroku上でGroongaをビルドする。

  2. ビルドしたGroongaをダウンロードできる場所にアップロードする。

  3. ビルドしたGroongaをダウンロードしてセットアップするbuildpackを作る。

  4. 作ったbuildpackをリリースする。

順に説明します。

Heroku上でGroongaをビルドしてアップロード

まず、次の2つを一緒に説明します。詳細は後述しますが、同じ処理の単位で実行しなければいけないからです。

  1. Heroku上でGroongaをビルドする。

  2. ビルドしたGroongaをダウンロードできる場所にアップロードする。

この2つを実現するビルド用のHerokuアプリケーションを作ります。Groongaの場合はheroku-groonga-builderというのがそれです。

このHerokuアプリケーションは次のことをします。

  1. Groongaのソースをダウンロード

  2. Groongaをビルド

  3. ビルドしたGroongaをアーカイブ

  4. アーカイブしたGroongaをアップロード

heroku-groonga-builderは何もしないRackアプリケーション(config.ruを置いているだけ)で、実際の処理はRakefileの中に書いています。

ソースのダウンロード、ビルド、アーカイブの処理は次のようなイメージです。

% curl -O http://packages.groonga.org/source/groonga/groonga-4.0.2.tar.gz
% tar xf groonga-4.0.2.tar.gz
% cd groonga-4.0.2
% ./configure --prefix=$HOME/vendor/groonga
% make
% make install
% cd -
% tar cJf heroku-groonga-4.0.2.tar.xz vendor/groonga

実際は次のようにrakeを実行して↑の処理を実施しています1

% heroku run:detached rake

detachedを使っているのは、Groongaのビルドにとても時間がかかるからです。だいたい6時間くらいかかります2

アーカイブしたGroongaは同じプロセス内でアップロードする必要があります。なぜなら、プロセスが終了するとビルドしたアーカイブも消えるからです。これが後述すると書いていた同じ処理で実行しなければいけない理由です。

アーカイブしたGroongaはGitHubのreleaseページにアップロードしています。例えば、Groonga 4.0.2の場合は次のページです。

Heroku上からアップロードするのでGitHubにアクセスするためのAPIキーをHerokuアプリケーションに渡さないといけません。APIキーはセキュリティー上で重要な値です。heroku-groonga-builderではこの情報を環境変数で渡しています。環境変数名はGITHUB_TOKENです。

環境変数で渡すには次の2つの方法があります。

  • heroku config:set GITHUB_TOKEN=xxx
  • heroku run:detached rake GITHUB_TOKEN=xxx

前者はHerokuの仕組みを使って設定する方法で、後者はRakeの仕組みを使って設定する方法です。前者はheroku config:get GITHUB_TOKENで、後者はheroku psで後から値を確認できるので、安全性という面ではどっちもどっちです。毎回新しいAPIキーを生成してそれを使い、ビルドが終わったら破棄するくらいがよいのではないかという案がありますが、実装はしていません。

APIキーを使ってアップロードする方法にはいくつかあります。Go言語で書かれたgithub-releaseというツールを使う方法や、Octokitなどのライブラリーを使う方法です。

heroku-groonga-builderは以前はgithub-releaseを使っていましたが、今はOctokitを使っています。

ダウンロードしてセットアップ

HerokuでビルドしたGroongaができたのでそれを使ってHerokuアプリケーション用の環境をセットアップします。これをするモジュールがheroku-buildpack-groongaです。これはbuildpackの一種です。

実はheroku-buildpack-groongaの中でGroongaをビルドするという選択肢もあるのですが、そうするとgit push heroku masterする毎にGroongaのビルドのために6時間くらいかかるので現実的ではありません。ビルド済みのGroongaをダウンロードすることで時間を短縮しています。

buildpackは次の3つのプログラムが必須です。すべて新規で実装します。実行ファイルになっていれば実装言語は問いません。bashで実装してもRubyで実装しても構いません。

  • bin/detect
  • bin/compile
  • bin/release

bin/detectは、このbuildpackを使おうとしているHerokuアプリケーションがこのbuildpackが要求する事前条件を満たしているかをチェックします。例えば、Rubyのbuildpackは「Gemfileが存在すること」が事前条件で、heroku-buildpack-groongaは「groonga/ディレクトリーが存在すること」が事前条件です。

bin/compileは、Herokuアプリケーションが必要なソフトウェアをインストールします。例えば、heroku-buildpack-groongaならアーカイブを展開します。

bin/releaseは、Herokuアプリケーションが使うデフォルトの設定を返します。例えば、環境変数だったりサービスを起動するコマンドラインなどの設定を返します。heroku-buildpack-groongaは環境変数PATHの設定などを返します。

詳細は公式サイトのドキュメントやheroku-buildpack-groongaの実装を参照してください。なお、heroku-buildpack-groongaはRubyで実装しています。

buildpackの動作確認用Herokuアプリケーションがあると便利です。heroku-buildpack-groongaを使ったHerokuアプリケーションは次のコマンドで作成できます。

% heroku apps:create --buildpack https://github.com/groonga/heroku-buildpack-groonga

buildpackを修正した場合はHerokuアプリケーションをgit push heroku masterしてください。heroku ps:restartでは新しいbuildpackは動きません。既存のbuildpack実行結果を再利用します。

buildpackをリリース

buildpackが動くようになったらリリースします。リリース用のプラグインがあるのでインストールします。

% heroku plugins:install https://github.com/heroku/heroku-buildpacks

これでheroku buildpacks:publishが使えるようになります。buildpacks:publish時に指定する名前は#{グループ}/#{名前}とする習慣があるようなので、heroku-buildpack-groongaはgroonga/groongaを使っています。

% heroku buildpacks:publish groonga/groonga

これでbuildpackをS3からダウンロードできるようになります。URLは次のようになります。

https://codon-buildpacks.s3.amazonaws.com/buildpacks/#{グループ}/#{名前}.tgz

例えば、groonga/groongaならこうなります。

https://codon-buildpacks.s3.amazonaws.com/buildpacks/groonga/groonga.tgz

ユーザーにはS3からダウンロードしてもらうようにしましょう。

まとめ

Heroku用Groongaのビルド方法を説明しました。ビルドするには次の4つの手順があります。

  1. Heroku上でGroongaをビルドする。

  2. ビルドしたGroongaをダウンロードできる場所にアップロードする。

  3. ビルドしたGroongaをダウンロードしてセットアップするbuildpackを作る。

  4. 作ったbuildpackをリリースする。

このうち、前半の2つがheroku-groonga-builderで実施していることで、後半の2つがheroku-buildpack-groongaが実施していることです。

HerokuにインストールされていないソフトウェアをHerokuで使えるようにしたいときの参考にしてください。

おまけ: heroku-buildpack-rroonga

おまけで、Rroonga用のbuildpackであるheroku-buildpack-rroongaの作り方についても簡単に説明します。

このbuildpackはGroongaのbuildpackとRubyのbuildpackを一緒に使います。次のようなイメージです。

  • bin/detectが呼ばれたとき
    • GroongaのbuildpackとRroongaのbuildpackのbin/detect相当の処理をする
  • bin/compileが呼ばれたとき
    • GroongaのbuildpackとRroongaのbuildpackをダウンロード
    • それぞれのbin/compileを実行
    • それぞれのbin/releaseも実行して結果をマージして保存
  • bin/releaseが呼ばれたとき
    • bin/compileのときに保存したbin/releaseをマージした結果をそのまま出力

関連記事: HerokuでRroongaを使う方法

  1. 以前はVulcanというツールを使っていましたが、今はheroku runを使うように変わっています。

  2. 最適化を有効にしてビルドした場合です。メモリー使用量は6GBを超えます。はっきり言ってこれはリソースを使い過ぎています。いつHerokuでビルドできなくなってもおかしくはありません。2つまで無料の1XというDynoで使えるメモリーは512MBで、そのDynoでビルドしていると「Error R14 (Memory quota exceeded)」というメッセージがログに出力されます。ただ、プロセスは殺されないので今は1XというDynoでビルドしています。