2015-10-16

CommaFeed を Cloud Foundry で動かす

「Cloud Foundry 百日行」第80日目,今日は「個人的に探しているフィード・リーダー」シリーズ (第1弾: Feedbin, 第2弾: Tiny Tiny RSS) の第3弾 (&多分最後になる予定) で CommaFeed です。Java の Dropwizard という framework を使って実装されています。

基本情報

手順の概要は以下の通りです。

  • 1) ソースコードの取得
  • 2) アプリのビルド
  • 3) サービスの作成とバインド
  • 4) 設定ファイルの作成とJARファイルの更新
  • 5) 環境変数の設定 (manifest.yml の作成)
  • 6) アプリのデプロイ
  • 7) 動作確認

1. ソースコードの取得

GitHub からソースコードを clone して,ディレクトリーを移動します。

$ git clone https://github.com/Athou/commafeed.git
..
$ cd commafeed/

2. アプリのビルド

Cloud Foundry の java-buildpack では,アプリをあらかじめビルドしてからデプロイする必要があります。
アプリの README の記述 (リンク) を参考に,ビルドを行います。

$ ./mvnw clean package
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building CommaFeed 2.3.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
..
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:52 min
[INFO] Finished at: 2015-10-12T04:57:03+09:00
[INFO] Final Memory: 60M/569M
[INFO] ------------------------------------------------------------------------

target/commafeed.jar ができているはずです。

$ ls target/commafeed.jar
target/commafeed.jar

3. サービスの作成とバインド

CommaFeed はデータの永続化に DBMS を使います。デフォルトでは H2 を使うようになっているのですが,これはローカルファイルにデータを格納するようになっているので,Cloud Foundry 上だと再起動でデータが消えてしまいます。そこで今回は PostgreSQL サービスを使うことにしました。

アプリのアップロード

アプリを停止状態で Cloud Foundry 上に push します。

$ cf push commafeed -p target/commafeed.jar --no-start
Creating app commafeed in org nota-ja / space 100 as nota-ja...
OK
..

サービスの作成

PostgreSQL サービスを作成します。

$ cf create-service PostgreSQL "Basic PostgreSQL Plan" pg-commafeed
Creating service instance pg-commafeed in org nota-ja / space 100 as nota-ja...
OK
..

サービスのバインド

アプリとサービスをバインドします。

$ cf bind-service commafeed pg-commafeed
Binding service pg-commafeed to app commafeed in org nota-ja / space 100 as nota-ja...
OK
..

4. 設定ファイルの作成とJARファイルの更新

CommaFeed の起動には設定ファイルが必須なので,作成します。さらに,その設定ファイルをアップロードできるよう,JARファイルに格納します。

設定ファイルの作成

config.yml.example をコピーして,内容を適宜修正します。

$ cp config.yml.example config.yml
$ emacs config.yml

主な修正は,以下の3点です。

  • pulicUrl
    アプリの URL と一致するように設定してください
  • allowRegistrations
    アプリケーション画面からのユーザー登録を可能にしてください
    本アプリは管理用画面があり,そこからユーザー登録することもできるのですが,Cloud Foundry 上では今のところ1つのアプリに複数のポートを割り当てることができないので(現在それを可能にする作業が進められています),今回はアプリケーション画面からの登録を可能にするようにしました
  • database
    cf env を実行して, VCAP_SERVICES のデータベース接続情報に基づいて値を設定してください
$ cf env commafeed
Getting env variables for app commafeed in org nota-ja / space 100 as nota-ja...
OK

System-Provided:
{
 "VCAP_SERVICES": {
  "PostgreSQL": [
   {
    "credentials": {
     "uri": "postgres://ea4badfa-a871-4237-a534-9d69fb464200:v2qmkpa772n1r35gdqrko158nr@192.168.15.91:5432/ea4badfa-a871-4237-a534-9d69fb464200"
    },
    "label": "PostgreSQL",
    "name": "pg-commafeed",
    "plan": "Basic PostgreSQL Plan",
    "tags": [
     "PostgreSQL",
     "Database storage"
    ]
   }
  ]
 }
}
..

最終的な変更箇所は以下のようになりました:

$ git diff --no-index -- config.yml.example config.ymldiff --git a/config.yml.example b/config.yml
index 5f6d167..2f7e219 100644
--- a/config.yml.example
+++ b/config.yml
@@ -2,13 +2,13 @@
 # ------------------
 app:
   # url used to access commafeed
-  publicUrl: http://localhost:8082/
+  publicUrl: http://commafeed.10.244.0.34.xip.io/^M

   # wether to allow user registrations
-  allowRegistrations: false
+  allowRegistrations: true^M

   # create a demo account the first time the app starts
-  createDemoAccount: false
+  createDemoAccount: true^M

   # put your google analytics tracking code here
   googleAnalyticsTrackingCode:
@@ -49,7 +49,7 @@ app:
   queryTimeout: 0

   # time to keep unread statuses (in days), 0 to disable
-  keepStatusDays: 0
+  keepStatusDays: 90^M

   # entries to keep per feed, old entries will be deleted, 0 to disable
   maxFeedCapacity: 500
@@ -75,10 +75,10 @@ app:
 # url is jdbc:jtds:sqlserver://localhost:1433/commafeed;instance=<instanceName, remove if not needed>

 database:
-  driverClass: org.h2.Driver
-  url: jdbc:h2:/home/commafeed/db;mv_store=false
-  user: sa
-  password: sa
+  driverClass: org.postgresql.Driver^M
+  url: jdbc:postgresql://192.168.15.91:5432/ea4badfa-a871-4237-a534-9d69fb464200^M
+  user: ea4badfa-a871-4237-a534-9d69fb464200^M
+  password: v2qmkpa772n1r35gdqrko158nr^M
   properties:
     charSet: UTF-8
   validationQuery: "/* CommaFeed Health Check */ SELECT 1"
@@ -95,9 +95,9 @@ server:
       port: 8084

 logging:
-  level: WARN
+  level: INFO^M
   loggers:
-    com.commafeed: INFO
+    com.commafeed: DEBUG^M
     liquibase: INFO
     io.dropwizard.server.ServerFactory: INFO
   appenders:

さきに挙げた主要3点以外については,各自お好みに合わせて設定してください。

JAR ファイルの更新

作成した設定ファイルを Cloud Foundry 上に持っていくために,target/commafeed.jar に追加します。

$ jar uvf target/commafeed.jar config.yml
adding: config.yml(in = 3411) (out= 1531)(deflated 55%)

5. 環境変数の設定 (manifest.yml の作成)

Cloud Foundry の java-buildpack で Dropwizard の JAR ファイルを起動するには,

  • java コマンドの引数で待受ポートを指定する
  • Main class (com.commafeed.CommaFeedApplication) の引数でコマンドと設定ファイルを指定する

必要があります。

今回は,以下の方法を用いました。

  • java コマンドに引数を渡す方法として JAVA_OPTS 環境変数を使う (参考リンク)
  • Executable JAR の Main-Class で指定されたクラスに引数を渡す方法として JBP_CONFIG_JAVA_MAIN 環境変数を使う (参考リンク)
    【余談】
    • これは,もともとは java-buildpack を fork して, config/java_main.yml を書き換えるという方法で行うものでした
    • v3.0 で,これら設定ファイルの中身を環境変数から与える方法が導入されて,いちいち fork をしなくて済むようになりました
    • この「環境変数から与える方法」は,少しトリッキーなのですが,概略は以下のようになります
      config/<設定名>.yml (例: open_jdk_jre.yml) というファイルの中身を環境変数から与える場合:
      • JBP_CONFIG_<大文字化した設定名> (例: JBP_CONFIG_OPEN_JDK_JRE) という環境変数に,
      • flow-style の YAML で設定を記述する (例: '[jre: { version: 1.7.0_+ }]')

これらの環境変数設定も含め,アプリの push に必要な情報を manifest.yml にまとめます。

$ cat manifest.yml
---
applications:
- name: commafeed
  path: target/commafeed.jar
  memory: 1024M
  buildpack: https://github.com/cloudfoundry/java-buildpack.git#v3.3
  services:
  - pg-commafeed
  env:
    JAVA_OPTS: '-Djava.net.preferIPv4Stack=true -Ddw.server.applicationConnectors[0].port=\$PORT'
    JBP_CONFIG_JAVA_MAIN: '[arguments: "server ./config.yml"]'

メモリは多めに1GBに設定しました。また config/java_mail.yml のサポートは java-buildpack v3.2 からで,今回使用した bosh-lite ベースの Cloud Foundry 環境 (cf-release v211) の標準である java-buildpack v3.0 ではサポートされていなかったので,最新のリリースである v3.3 をインターネット上から取ってくるように設定しました。

6. アプリのデプロイ

準備が整ったので,アプリをデプロイします。

$ cf push
..
requested state: started
instances: 1/1
usage: 1G x 1 instances
urls: commafeed.10.244.0.34.xip.io
last uploaded: Mon Oct 12 06:56:07 UTC 2015
stack: cflinuxfs2
buildpack: https://github.com/cloudfoundry/java-buildpack.git#v3.3

     state     since                    cpu      memory         disk      details
#0   running   2015-10-12 04:35:59 PM   105.4%   485.1M of 1G   0 of 1G

起動しました。

7. 動作確認

アプリのURLにアクセスすると,Welcome 画面にリダイレクトされます:

ユーザーを登録します:

ユーザー登録が済むと,自動的にログイン状態になります:

左上の【Subscribe】ボタンを押して,フィードを登録してみます:

登録に成功すると,未読記事のタイトル一覧が表示されます:

記事タイトルをクリックすると,記事を読むことができます:

上部やや右よりにある歯車形ボタンをクリックすると,設定画面に入れるので,言語を日本語にしてみます:

【Save】をクリックすると通常画面に戻ります。

メニュー等が日本語になっていることが確認できました:

以上で動作確認は終わりです。

使ってみた印象では,メモリは多めに必要ですが,動作は軽快で安定していて,機能はシンプルですが必要なものは揃っている感じです。日本語のサポートは珍しいと感じました。

このアプリは,他にパスワードを忘れた際のメイル送信機能や,Redis をキャッシュとして利用する機能もありますが,今回は時間切れで試せませんでした。また,管理者画面についても今回は動作確認対象から外しましたが, JAVA_OPTS の設定を変更して管理者画面にアクセスできることは確認できたので,切り替えができるようにしたいとは思いました。

今回使用したソフトウェア