これまで何回か Azure Web Apps 上で Rails を動かしてきましたが、簡単に使えるデプロイ可能にしようとすると bundle install でエラーになる謎現象に阻まれて諦め気味でした。*1
ふと JRuby でも動くことを思い出したのと、以前に Scott Hanselman がブログで書いていたので Web Apps にデプロイするカスタムデプロイスクリプトを作成しました。
結果としては、必要なファイルをコピーして少し修正するぐらいで Web Apps へ Rails 4 アプリをデプロイ出来るようになりました。GitHub にサンプルを上げてあります。
リポジトリ内にある必要なファイルは以下の 5 つになります。
- .deployment
- deploy.cmd
- Web Apps のカスタムデプロイスクリプト
- Procfile
- startup.cmd
- 以前に作った foreman っぽく使うスクリプト*2
- Web.config
- HttpPlatformHandler を使うための設定
JRuby のバージョンは決め打ちにしてあります。細かい説明は後にして、とりあえず空っぽの Web App を用意してデプロイしてみましょう。
このリポジトリをフォークするなどして Azure Web Apps にデプロイするだけで、自動的に JRuby のインストールを行い、その後 bundle install を実行して必要な gem を全てインストールするようになっています。
JRuby 1.7.20 をインストールしていることが確認出来ます。その後に bundler も一緒にインストールします。
wwwroot 以下に KuduSync.NET でファイルをコピーした後には、bundle install を実行し必要な gem のインストールを行います。これも少し時間がかかります。
暫く待つとデプロイが完了するので、ブラウザからサイトへアクセスしてみます。ちなみに私が B1 インスタンスで試したところ、立ち上がるのに 2 分近くかかりました。
気長に待つとプロセスが立ち上がるので、その後はサクサク動作するようになります。
環境情報にちゃんと JRuby で動作していることが表示されています。
実用的かと言われると、起動の遅さは Azure Web Apps のストレージパフォーマンスに問題があると思っているので、このあたりが改善されるまでは Always On で誤魔化すぐらいしか出来ないかなと思ってます。
この後はテンプレートに行った修正をまとめます。
Gemfile に puma を追加する
RubyInstaller の時には thin を使いましたが、JRuby では puma が使えるらしいのでこっちを使いました。
gem 'puma'
Gemfile に上の 1 行を追記するだけです。
sqlite3 のインストールが失敗する
標準で Gemfile に追加されている sqlite3 のインストールに失敗したので、以下のページを参考にして Gemfile を修正しました。
JRuby on RailsでSQLite3を使うための覚え書き - NAT’s Programming Champloo
sqlite3 となっている部分を、以下のように修正するだけでした。
gem 'activerecord-jdbcsqlite3-adapter'
これだけで依存関係で色んなものが入ってくれるみたいです。
tzinfo-data が存在しないエラーになる
puma が起動して、最後の最後に tzinfo-data のデータソースが読み込めないというエラーが発生しました。少し検索すると簡単に解決策が見つかりました。
Resolving TZInfo::DataSourceNotFound Errors · tzinfo/tzinfo Wiki · GitHub
元々が Windows で作った Gemfile なので、指定が抜けていただけのようです。
gem 'tzinfo-data', platforms: [:mingw, :mswin, :jruby]
この修正で、問題なくデプロイから実行までスムーズに行くようになりました。
追記:スタートアップ時間について
JRuby の Wiki にスタートアップ時間を改善する方法がいくつか書いてありました。
Improving startup time · jruby/jruby Wiki · GitHub
いくつかを試してみましたが、どれも効果はないように感じました。やはりストレージ周りかもしれません。
クライアント VM を使う方法に関しては、Azure Web Apps の制約があるのかわかりませんが JAVA_HOME を変更できず、常に 64bit 版の Java 1.7.0_51 が使われてしまうみたいでした。