April 20, 2009

Sinatra が Google App Engine で動くまで

(注: Google App Engine を GAE と略すことがあります。)

Sinatra を Google App Engine で動かしてみました。

Github にすぐに動かせるものを置いておいたので、手っ取り早く試したい人はここからソースを取ってきて動かしてみるといいと思います。
appengine-java-sdk は別途必要です。

http://github.com/jugyo/sinatra_on_gae/tree/master

詳細は同梱されている README を参照してくだい。

以下は、ちゃんと手順を追って試してみたい人向けの解説です。

SDK のダウンロード

SDK をマシンに入れておく必要があります。
以下から appengine-java-sdk-1.2.0.zip というのをダウンロードして適当な場所に解凍してください。

http://code.google.com/appengine/downloads.html

PATH の設定

SDK の bin ディレクトリを PATH に追加しておきます。
コマンドを実行するときにフルパスを指定するのが面倒なので。

例:

export PATH=$PATH:~/src/jruby/appengine-java-sdk-1.2.0/bin

アプリケーションのフォルダを作成

フォルダをいくつか作ります。

cd sinatra_on_gae
mkdir WEB-INF
mkdir WEB-INF/gems WEB-INF/lib

ライブラリのインストール

必要なライブラリを gem でインストールします。
その際、-i オプションでディレクトリを指定します。
さらに、rdoc や ri はいらないので –no-rdoc –no-ri オプションも付けておきます。

gem install -i WEB-INF/gems sinatra --no-rdoc --no-ri

以下のファイルは不要なので削除しておきます。

rm -rf WEB-INF/gems/bin WEB-INF/gems/cache/*

jar ファイルの用意

WEB-INF/lib に以下の jar ファイルを置きます。

appengine-api-1.0-sdk-1.2.0.jar
jruby-core.jar
ruby-stdlib.jar
jruby-rack-0.9.4.jar

appengine-api-1.0-sdk-1.2.0.jar は SDK に含まれているライブラリで、 jruby-core.jar と ruby-stdlib.jar は、Github から取ってきた JRuby をビルドして必要なものだけ抜き出したものです。
jruby-rack-0.9.4.jar も Github から取ってきてビルドしました。

Sinatra アプリケーションを作成

Sinatra 上で動かすアプリケーションを作ります。

WEB-INF/app.rb

require 'rubygems'
require 'sinatra'

get '/' do
  'Hello World!!'
end

やっぱり Sinatra はシンプルでいいですね〜。

appengine-web.xml の作成

GAE アプリケーションとしての設定を appengine-web.xml というファイルに書きます。

WEB-INF/appengine-web.xml

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
    <application>sinatra_on_gae</application>
    <version>1</version>
    <static-files />
    <resource-files />
    <sessions-enabled>false</sessions-enabled>
    <system-properties>
      <property name="jruby.management.enabled" value="false" />
      <property name="os.arch" value="" />
      <property name="jruby.compile.mode" value="JIT"/> <!-- JIT|FORCE|OFF -->
      <property name="jruby.compile.fastest" value="true"/>
      <property name="jruby.compile.frameless" value="true"/>
      <property name="jruby.compile.positionless" value="true"/>
      <property name="jruby.compile.threadless" value="false"/>
      <property name="jruby.compile.fastops" value="false"/>
      <property name="jruby.compile.fastcase" value="false"/>
      <property name="jruby.compile.chainsize" value="500"/>
      <property name="jruby.compile.lazyHandles" value="false"/>
      <property name="jruby.compile.peephole" value="true"/>
   </system-properties>
</appengine-web-app>

web.xml の作成

Web アプリケーションの設定を web.xml に記述します。

WEB-INF/web.xml

<!DOCTYPE web-app PUBLIC
  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>

  <context-param>
    <param-name>public.root</param-name>
    <param-value>/</param-value>
  </context-param>

  <context-param>
    <param-name>rackup</param-name>
    <param-value>require 'rubygems'
require 'sinatra'

root_dir = File.dirname(__FILE__)

#set :environment, :production
set :environment, :development
set :root,        root_dir
set :app_file,    File.join(root_dir, 'app.rb')
disable :run

require 'app'

run Sinatra::Application
</param-value>
  </context-param>

  <context-param>
    <param-name>jruby.min.runtimes</param-name>
    <param-value>1</param-value>
  </context-param>

  <context-param>
    <param-name>jruby.max.runtimes</param-name>
    <param-value>1</param-value>
  </context-param>

  <context-param>
    <param-name>jruby.init.serial</param-name>
    <param-value>true</param-value>
  </context-param>

  <filter>
    <filter-name>RackFilter</filter-name>
    <filter-class>org.jruby.rack.RackFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>RackFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <listener>
    <listener-class>org.jruby.rack.RackServletContextListener</listener-class>
  </listener>

</web-app>

sinatra のソースをちょっとだけ修正する必要があります。
WEB-INF/gems/gems/sinatra-0.9.1.1/lib/sinatra.rb の8行目です

use_in_file_templates!

#use_in_file_templates!

use_in_file_templates! というのはおそらく、ファイルの中にテンプレートを書いておける機能にまつわるメソッドだと思います。
ま、いらないと思います。

GAE のアプリとして起動する

さて、以上でアプリケーションを動かす準備が整いました。
以下のようにして起動するとこができます。

dev_appserver.sh .

ちなみに、起動の際には WEB-INF ディレクトリが置かれているディレクトリを指定する必要があります。

普通の Ruby で起動する

普通の Ruby でも当然動きます。

GEM_HOME=WEB-INF/gems ruby ./WEB-INF/app.rb

デプロイ

appengine-web.xml の application と version を適切に設定した上で以下を実行するとデプロイできます。

appcfg.sh update .

当然、Google App Engine のアカウントを持っていてかつ Java が使えるようなっている必要があります。

デモ

以下で実際に動かしてます(一週間くらいは動かしておくつもりです。Hello World!! しか出ませんけどね!)。

http://jugyo-test.appspot.com/

参考:
http://blog.bigcurl.de/2009/04/running-sinatra-apps-on-google.html