Haskell on Heroku

HaskellのScottyで Webサーバを書いていたのですが、Herokuへのdeployがうまくできたので手順をメモしておきます。yesod on heroku 等は結構検索で引っかかるんですが、新旧が色々と混じっているので現時点でのまとめになります。
環境は、MacOS MountainLionです。

まず前提として、HerokuでHaskellのWebサーバを動かすには、binaryを手元で生成して上げてdeploy後にキックする形になります。そのため、Herokuで使っている Ubuntuの10.04 LTS 上でbinaryをbuildするのが一番確実です。それさえ準備できれば、後はnode.jsを動かすのと同じような形で動かすことができます。

Webサーバの起動ファイルを用意する

binaryを生成する際の注意点としては、ライブラリのインストールを別途行うことはできないのでstatic linkするようにbuildする必要があります。Haskellでしたら、cabalファイルに「ghc-options: -static」を追加して上げるのが良いです。
次に以下のコマンドでpackage.jsonを生成します。

$ echo '{ "name": "first-yesod", "version": "0.0.1", "dependencies": {} }' >> package.json

最後に、ProcFileを以下の内容で準備します*1。以下のコマンドでdeployしたWebサーバが起動するので、listenするport番号は起動時に $PORTで指定できるようにしておく必要があります。

web: ./dist/build/my-server/my-server --port $PORT

ここまで準備ができたら、一旦gitリポジトリへコミットしておきます。

Vagrantを使って build環境を構築する。

http://vagrantup.com/v1/docs/getting-started/index.html
このページを参考に、VirtualBoxVagrantをインストールします。
その後、別のフォルダへ移動し以下のコマンドを実行します。

$ git clone git@bitbucket.org:puffnfresh/vagrant-haskell-heroku.git
$ cd vagrant-haskell-heroku
$ vargant up
$ vargant ssh

vargant upで結構な時間がかかりますが、問題なく終わればこれでVMsshで接続した状態になります。このVMはUbuntu10.04 LTSに、ghc7.4.1 とcabal1.14.0 が既にインストールした状態になっています。gitコマンドやheroku toolbeltは未インストールなので、以下のコマンドでインストールしてあげます。

$ sudo apt-get install git-core
$ wget -qO- https://toolbelt.heroku.com/install-ubuntu.sh | sh
$ ssh-keygen -t rsa
$ heroku keys:add
$ heroku login

最後にherokuにnode.jsようのappを生成します。既に作成済みの場合には不要です。

$ heroku create --stack cedar

以上で、環境構築は完了です。

herokuへdeployする

これまでの手順で環境構築はできたので、最後にbuildしてdeployしてあげます。vargant に接続したままで以下のように実行します。

$ git clone git@repository:my-server.git
$ cd my-server
$ git checkout -b deploy
$ cabal update
$ cabal install
$ git add -f dist/build/my-server/my-server
$ git commit -m "Deploy `date`"
$ git remote add heroku git@heroku.com:my-server.git
$ git push -f heroku deploy:master

これで、deployが完了です。

$ heroku open

このコマンドで、実行結果を確認できます。エラーが表示された場合には、以下のコマンドでログを確認しましょう。

$ heroku logs

*1:my-server が今回作成するアプリ名です