オープンソースのPaaSソフトウェア CloudFoundry の技術情報やイベント告知などを掲載します

2015-10-14

EtherDraw を Cloud Foundry で動かす

「Cloud Foundry 百日行」第78日目,今回は「Etherシリーズ(?)」の描画アプリ,EtherDraw です。複数人で画面を共有してキャンバスに絵を描くことができるアプリで,描画機能としては基本的なものしかありませんが,子どもたちに使ってもらったりすると面白いかもしれません。あとは,遠隔でのホワイトボード共有には使えそうです。終わったら SVG / PNG でエクスポートできるので情報の保存も容易ですし,物理ホワイトボードと違って消去もワンクリックで済みます。

基本情報

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

  • 1) ソースコードの取得
  • 2) デプロイ準備
  • 3) アプリのデプロイ
  • 4) 動作確認
  • 5) 永続化

1. ソースコードの取得

GitHub からソースコードを clone します。今回はディレクトリー名を指定して clone しています。

$ git clone https://github.com/JohnMcLear/draw.git etherdraw

ディレクトリーを移動します。

$ cd etherdraw/

2. デプロイ準備

2.1. node モジュールの事前インストール

このままの状態で Cloud Foundry にデプロイするとステージングに失敗したので,調査した結果,このアプリで利用している canvas というモジュールに問題があることがわかりました。

cf. gyp: fix pangocairo detection by LinusU - Pull Request #600 - Automattic/node-canvas

このままでは動作しないので,上記 pull request で提案されている node モジュールのインストールを実行します。

$ npm install LinusU/node-canvas#pangocairo-test

これで,Cloud Foundry 上で compile 時に問題を起こすモジュールの修正版がローカルに生成され, cf push の際にソースコードと一緒にアップロードされるので,ステージングに失敗しなくなります。

【注】必要ライブラリーの事前インストール

ローカル環境でこの npm install を成功させるには, このページ (リンク) に書かれているライブラリーを事前にインストールしておくことが必要です。

もし上記 npm コマンドの実行に失敗した場合は,以下を実施後,再度実行してみてください。

以下はローカル環境が Ubuntu であるという前提で進めます。他の環境については, ここ (リンク) からご自分の環境を選んで,その記述に従ってください。

Ubuntu では,以下を実行します。

$ sudo apt-get update 
$ sudo apt-get install libcairo2-dev libjpeg8-dev libpango1.0-dev libgif-dev build-essential g++

これにより,node モジュールのインストールに必要なライブラリーがインストールされます。

2.2. package.json の修正

2.1 節のコマンドの実行に成功すると,使われる canvas モジュールのバージョンが変わるので,それに合わせて package.json を修正します。

$ emacs package.json
..
$ git diff -- package.json
diff --git a/package.json b/package.json
index de5bd41..b5d9369 100755
--- a/package.json
+++ b/package.json
@@ -14,7 +14,7 @@
     "socket.io": "~1.0.0",
     "async": "~0.6.2",
     "ueberDB": "~0.2.1",
-    "canvas": "1.2.1",
+    "canvas": "1.2.4",
     "paper": "0.9.22",
     "jsonminify":"~0.2.3"
   }

2.3. アプリの待受ポートの修正

本アプリは待受ポートを環境変数から設定することができないので,それができるようにソースコードを修正します。

$ emacs server.js
..
$ git diff -- server.js
diff --git a/server.js b/server.js
index 598bf88..6627f53 100755
--- a/server.js
+++ b/server.js
@@ -15,6 +15,10 @@ var settings = require('./src/util/Settings.js'),
     http = require('http'),
     https = require('https');

+if (process.env.PORT) {
+    settings.port = process.env.PORT;
+}
+
 /**
  * SSL Logic and Server bindings
  */

これで, PORT という環境変数がある場合はその値を使い,ない場合は従来通りの動作になります。

2.4. settings.json の作成

最後に,設定ファイル settings.json を作成します。といっても,テンプレートをコピーするだけです。

$ cp settings.json.template settings.json

この設定では,データの保存先としてファイルを使用する DBMS である dirtydb を使うので,再起動するとデータが全て消えてしまいますが,試しに使うだけであればこれでOKですので,今回はこのままで行きます。

外部のデータベースにデータを永続化する方法については,5 節に書きますので,そちらをご覧ください。

3. アプリのデプロイ

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

$ cf push etherdraw
..
OK

App etherdraw was started using this command `node server.js`

Showing health and status for app etherdraw in org nota-ja / space 100 as nota-ja...
OK

requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: etherdraw.10.244.0.34.xip.io
last uploaded: Wed Oct 14 04:20:38 UTC 2015
stack: cflinuxfs2
buildpack: Node.js

     state     since                    cpu    memory           disk      details
#0   running   2015-10-14 01:27:56 PM   0.0%   104.5M of 256M   0 of 1G

起動しました。

4. 動作確認

アプリのURLにアクセスすると,ランダム生成された URL を持つ作業画面にリダイレクトされます:

ブラシで字を書いてみました:

ペンで字を書いてみました:

色を変えてみます:

ブラシで色を塗ってみました:

他の人にアクセスしてもらって,絵を描いてもらいました:

わかりにくいかもしれませんが,右上の人型アイコンの横の数字が, 2 になっています。

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

5. 永続化

さて,このままですと,(さきに述べたように) アプリが再起動されるとせっかく描いた絵が全て消えてしまいます。描いた絵が消えないようにするためには,データベースを使って永続化します。DBMS としては, settings.json.template 内で例として挙げられている MySQL を使うことにしました。

5.1. サービスの作成

$ cf create-service p-mysql 100mb mysql-etherdraw
Creating service instance mysql-etherdraw in org nota-ja / space 100 as nota-ja...
OK

5.2. アプリとサービスのバインド

$ cf bind-service etherdraw mysql-etherdraw
Binding service mysql-etherdraw to app etherdraw in org nota-ja / space 100 as nota-ja...
OK
TIP: Use 'cf restage etherdraw' to ensure your env variable changes take effect

5.3. データベース接続設定の変更

アプリが MySQL に繋がるよう,設定を変更します。

まず,データベース接続情報を cf env で確認します。

$ cf env etherdraw
..
 "VCAP_SERVICES": {
  "p-mysql": [
   {
    "credentials": {
     "hostname": "10.244.7.6",
     "jdbcUrl": "jdbc:mysql://10.244.7.6:3306/cf_486b7f41_74eb_4f55_adbb_f514e9c63f75?user=pBxKgJ3l5NDUi4WP\u0026password=1yOxeXgyHXXlGrc2",
     "name": "cf_486b7f41_74eb_4f55_adbb_f514e9c63f75",
     "password": "1yOxeXgyHXXlGrc2",
     "port": 3306,
     "uri": "mysql://pBxKgJ3l5NDUi4WP:1yOxeXgyHXXlGrc2@10.244.7.6:3306/cf_486b7f41_74eb_4f55_adbb_f514e9c63f75?reconnect=true",
     "username": "pBxKgJ3l5NDUi4WP"
    },
    "label": "p-mysql",
    "name": "mysql-etherdraw",
    "plan": "100mb",
    "tags": [
     "mysql"
    ]
   }
  ]
 }
..

上記の情報をもとに,設定ファイル settings.json のデータベース接続設定の部分を書き換えます。

元の設定との差分はこうなります。

$ git diff --no-index -- settings.json.template settings.json
diff --git a/settings.json.template b/settings.json
index c29599f..bba5e99 100644
--- a/settings.json.template
+++ b/settings.json
@@ -11,21 +11,23 @@

   //The Type of the database. You can choose between dirty, postgres, sqlite and mysql
   //You shouldn't use "dirty" for for anything else than testing or development
+  /*
   "dbType" : "dirty",
   //the database specific settings
   "dbSettings" : {
      "filename" : "var/dirty.db"
   },
+  */

-  /* An Example of MySQL Configuration
+  /* An Example of MySQL Configuration */
   "dbType" : "mysql",
   "dbSettings" : {
-    "user"    : "root",
-    "host"    : "localhost",
-    "password": "",
-    "database": "etherdraw"
+    "host"    : "10.244.7.6",
+    "port"    : 3306,
+    "user"    : "pBxKgJ3l5NDUi4WP",
+    "password": "1yOxeXgyHXXlGrc2",
+    "database": "cf_486b7f41_74eb_4f55_adbb_f514e9c63f75"
   },
-  */

   /* The default selected tool - 'pencil', 'brush', 'select' */
   "tool": "brush"

5.4. アプリの更新

設定ファイルの更新を反映させるため,アプリをプッシュします。

$ cf push etherdraw
..
     state     since                    cpu    memory           disk      details
#0   running   2015-10-14 01:21:31 PM   0.8%   105.1M of 256M   0 of 1G

起動しました。

5.5. 動作確認

こんな絵が描かれた状態で:

アプリを再起動します。

$ cf restart etherdraw

再起動中は 404 が出てアクセス不能になりますが:

     state     since                    cpu    memory           disk      details
#0   running   2015-10-14 03:06:42 PM   0.3%   104.4M of 256M   0 of 1G

アプリ起動後にアクセスすると,もとの絵が残っています:

(といってもこの図ではよくわかりませんが..)

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