Micro Cloud Foundry 上で Sinatra + MongoMapper アプリケーションを実行する

Sinatra + Haml で MongoDB を使う id:fits:20110306」で作成した Sinatra + Haml + MongoMapper のサンプルをプライベートクラウド PaaS 環境の Micro Cloud Foundry 上で実行してみました。

サンプルソースは http://github.com/fits/try_samples/tree/master/blog/20110917/


Micro Cloud Foundry は VMware用の仮想マシンイメージとして無償で配布されており、手軽にプライベートクラウドの PaaS 環境を構築できるようになっています。
個人的には Sinatra, Node.js, Grails 等のフレームワークをサポートしている点や MongoDB が使える点(MySQL や Redis も使える)が気に入っています。

アプリケーションの変更

id:fits:20110306 の MongoMapper 版サンプルをそのまま使い Micro Cloud Foundry 用に MongoDB の接続設定を書き換えます。

Micro Cloud Foundry 環境では、アプリケーションがバインドしているサービスの情報(今回は MongoDB)が VCAP_SERVICES という環境変数に設定されているので(形式は JSON)、この値をパースして DB への接続情報などを取得する事になります。

VCAP_SERVICES に設定された MongoDB 接続情報例
{"mongodb-1.8":[{"name":"mongodb-cad3a","label":"mongodb-1.8","plan":"free","tags":["mongodb","mongodb-1.8","nosql"],"credentials":{"hostname":"127.0.0.1","host":"127.0.0.1","port":25001,"username":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","password":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","name":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","db":"db"}}]}


下記では、VCAP_SERVICES から MongoDB 接続情報を取り出し、接続用の URI を組み立てて MongoMapper に接続設定を行っています。

site.rb
require "rubygems"
require "sinatra"
require "haml"
require "mongo_mapper"
require "json"

require "models/book"
require "models/user"
require "models/comment"

configure do
    # MongoDB 接続情報取り出し
    services = JSON.parse(ENV['VCAP_SERVICES'])
    mongoKey = services.keys.select{|s| s =~ /mongodb/i}.first
    mongo = services[mongoKey].first['credentials']

    # MongoDB 接続用 URI 組み立て
    uri = "mongodb://#{mongo['username']}:#{mongo['password']}@#{mongo['host']}:#{mongo['port']}/#{mongo['db']}"

    # MongoMapper 設定
    MongoMapper.connection = Mongo::Connection.from_uri(uri)
    MongoMapper.database = mongo['db']
end

get '/' do
    haml :index, {}, :books => Book.all(:order => 'title'), :users => User.all(:order => 'name'), :action => '/comments'
end
・・・

Micro Cloud Foundry 用に変更するのは MongoDB の接続に関する部分だけです。

アプリケーションのデプロイ

Micro Cloud Foundry のセットアップが済んでおり、クライアントから vmc で接続できるようになっているものとします。(参照 http://support.cloudfoundry.com/entries/20316811-micro-cloud-foundry-installation-setup

この状態でアプリケーションをデプロイ(vmc push)しても、MongoMapper がインストールされていないため以下のようなエラーが発生します。

デプロイ時のエラー例(MongoMapper 未インストール)
> vmc push msample
・・・
Staging Application: OK
Starting Application: .
Error: Application [msample] failed to start, logs information below.
====> logs/stderr.log <====

/var/vcap/data/packages/dea_ruby18/3/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:36:in `gem_original_require': no such file to load -- mongo_mapper (LoadError)
        from /var/vcap/data/packages/dea_ruby18/3/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:36:in `require'
        from site.rb:4

Should I delete the application? (Y/n)?


このような場合の Micro Cloud Foundry 的な対応方法が分からなかったので、とりあえず Micro Cloud Foundry 環境に SSH でログインし、/var/vcap/data/packages/dea_ruby18 の gem を使って MongoMapper をインストールしてみました。

SSH でログインする際のユーザー名は vcap、パスワードに Micro Cloud Foundry の画面で設定したパスワードを使う点に注意。(vmc のログインに使うユーザー名とは異なります)

MongoMapper のインストール例(SSH で Micro Cloud Foundry 環境にログイン)
vcap@micro:~$ sudo /var/vcap/data/packages/dea_ruby18/3/bin/gem install mongo_mapper


これでアプリケーションを正常に実行できるようになったはずですので、再度デプロイを実行します。(下記では site.rb の配置ディレクトリをカレントディレクトリにして vmc push を実行しています)

アプリケーションのデプロイ例
> vmc push msample
Would you like to deploy from the current directory? [Yn]:
Application Deployed URL: 'msample.fits.cloudfoundry.me'?
Detected a Sinatra Application, is this correct? [Yn]:
Memory Reservation [Default:128M] (64M, 128M, 256M or 512M)
Creating Application: OK
Would you like to bind any services to 'msample'? [yN]: y
Would you like to use an existing provisioned service [yN]?
The following system services are available:
1. mongodb
2. mysql
3. redis
Please select one you wish to provision: 1
Specify the name of the service [mongodb-cad3a]:
Creating Service: OK
Binding Service: OK
Uploading Application:
  Checking for available resources: OK
  Packing application: OK
  Uploading (3K): OK
Push Status: OK

Staging Application: OK

Starting Application: OK

無事成功しました。

上記では、アプリケーションのデプロイ時にバインドするサービス(mongodb-cad3a)も同時に作成していますが、事前に vmc create-service でサービスを作成しておき、後から vmc bind-service でアプリケーションにバインドする事も可能です。

なお、登録されているアプリケーションの状態は vmc apps で確認できます。

アプリケーション一覧
> vmc apps
+-------------+----+---------+-------------------------------+---------------+
| Application | #  | Health  | URLS                          | Services      |
+-------------+----+---------+-------------------------------+---------------+
| msample     | 1  | RUNNING | msample.fits.cloudfoundry.me  | mongodb-cad3a |
+-------------+----+---------+-------------------------------+---------------+

これで、Web ブラウザから msample.fits.cloudfoundry.me にアクセスすれば正常に動作している事を確認できるはずです。