これは,mruby advent calendar 2013の6日目の記事です.
ネタですが,Herokuでテキストを返すだけのHTTPサーバを構築してみます.
手順ですが,ローカルでビルドしてサーバを動かしてみてから,その手順をbuildpackに移植しています.今回書いたコードは,mruby-buildpackとmruby-test-serverにpushしてあるので,必要でしたら参照してください.
ちなみに,node.jsをよく引き合いにだすのは,今回はmruby-uvを使っているからと,わたしがnode.jsでしかherokuにdeployしたことがないからです.
まず,ローカルでの動作確認ですが,mruby-uvとmruby-httpの使い方の確認からはじめて,自前のbuild_config.rbでビルドして,mrubyでサンプルを元に書いたスクリプトを動かすといった流れでした.
ただ,ビルドの手順が鬼門でして,libuvのビルドから始めました.なぜかというと,node.jsのを使おうかと思ったのですが,何個かのuv.hを読んだ結果,最新のmasterにあるのと安定版ではエラー処理の方法が若干違うので諦めたからです.それと,Herokuでビルドするときにlibuvがインストールしてあるのかも不安でした.gypというビルドシステムを使っているようなのですが,gypを入れるのが煩雑そうだったので,とりあえずそこにあった生Makefileを使って静的ライブラリをビルドしてなんとかなりました.
mruby-uvもlibuvのバージョン間に互換性がないので,特別にpatchを書いて使っています.gemで:branchを指定できたのは助かりました.
それから,node.jsアプリみたいに環境変数を使いたかったので,mruby-envも入れて,動作確認に使っていたOS X向けのframeworkの設定やらをやって,なんとか"Hello World!"を返してくれるようになりました.
ここら辺の試行錯誤は,mruby-test-serverのrun-local.shに生かされています.
続いて,mruby用のbuildpackの作成に入りました.
その前に,「buildpackとはなんぞや?」なんですが簡単に言うと,gitリポジトリにあるコードをHerokuで動かせるようにするシェルスクリプトです.基本的なことはここに書いてあります.Ruby, node.jsなどメジャーな環境は大体既存のがあるので普通は自前で書くなんてことはないのですが,対応してないような言語を使うような場合は必要です.サードパーティ製のbuildpackもあるので参考にしたり,意外なbuildpackを見つけて面白がったりしてました.
mrubyにも既存のbuildpackがあるのですが,これはビルド済みのmrubyを使うので今回は特に使いませんでした.mrubyはbuild_config.rbを書いてなんぼです.
そして,実際のbuildpackを書き方なんですが,そうゆう人向けのページがあるのでこの通りに書いていけばいいです.detect/compile/releaseの3つのスクリプトを書いて,リポジトリにpush,そのリポジトリのURLをアプリにconfigコマンドでBUILDPACK_URLに設定するのが基本になります.detectはただのbuild_config.rbを探すだけ,compileはrun-local.shの焼き直し,releaseはserver.rbをデフォルトで実行する設定を出力するだけでした..profile.d/にPATHを設定するスクリプトを置くとか色々ありますが,大したことはしてないです.一応,一から書いたので,Cとnode.jsのbuildpackはちょろちょろ読みました.
そんな感じで大体buildpackが書けたら,BUILDPACK_URLを設定してpushして何度か試行錯誤すればHello World!を返してくれるようになります.
「コンソールとかただのテキストで出力されるHello World!とかださい」とずっと思っていたのですが,ちゃんとこの12文字を見ることができた時は大変感慨深かったです.
最後に,実際にmrubyで動いてるテキストでHello World!しか返せないhttpサーバは http://mruby-test-server.herokuapp.com/ なので是非みてってください.