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

2015-06-30

Jenkins を Cloud Foundry で動かす

「Cloud Foundry 百日行」第19日目は,皆さんご存知 CI (Continuous Integration) ツール Jenkins です。

実はこの記事を書こうとして検索した時に,以下のような記事を見つけたのですが,

立ち上げるだけであれば,本稿の手順だと,たったの2ステップ/5分程度 (注:ネットワークの速度に依存します) で終わります。記事を書く際は非常に楽でした。

基本情報

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

  1. コードの取得
  2. Cloud Foundry 環境への push
  3. 動作確認

コードの取得

参考情報にも記しましたが,2014年末,Cloud Foundry 開発者のメイリング・リストに, Jenkins のデプロイに関する投稿 があり,そのスレッドで jenkins-buildpack を使うとうまくいったという報告がありました。本稿でもこの方法を使います。

Buildpack の良い点の一つは,このように,他の人が作ったものを,繰り返し可能な手順 (自動化手順) として使わせてもらえるところにあると思います。

jenkins-buildpack の README に従い, Jenkins 公式サイトから 最新安定版の war ファイル を取得します。ちなみに,検証時点でのバージョンは 1.609.1 でした。

$ curl -L http://mirrors.jenkins-ci.org/war-stable/latest/jenkins.war -o jenkins.war

-L は,リダイレクトに従うためのオプションです。

Cloud Foundry 環境への push

先ほどダウンロードした war ファイルを,jenkins-buildpack を使って Cloud Foundry 上に push します。

$ cf push j -p jenkins.war -b https://github.com/Altoros/jenkins-buildpack.git -m 1G -t 180
Creating app j in org nota-ja / space 100 as nota-ja...
OK
.......
requested state: started
instances: 1/1
usage: 1G x 1 instances
urls: j.10.244.0.34.xip.io
last uploaded: Tue Jun 23 10:43:44 +0000 2015
stack: lucid64

     state     since                    cpu    memory         disk      details
#0   running   2015-06-23 07:44:34 PM   0.0%   256.4M of 1G   0 of 1G

スムーズに起動しました。ダウンロードしてpush。これだけです。

ポイントは,

  • メモリ1GB以上を指定すること
    メモリが不足している場合,起動に失敗します
  • タイムアウトを長め(上の例では180秒)に取ること
    war ファイルのサイズ自体が大きく,アップロードに時間がかかるのに加えて,jenkins-buildpack がダウンロード/展開するファイルの量も多いので,長めに取っておくに越したことはありません
    (もっとも,今回実際にかかった時間は1分15秒程度でしたが)

動作確認

ブラウザーでアクセスしてみます。

最初の画面:

ちゃんと起動しています。

ジョブを作ってみます。

ジョブ設定画面:

ジョブ完成:

ビルド結果 (コンソール) :

問題なく動作しています。

なお,push したままの状態では何のセキュリティもない状態なので,気になる方はユーザーを作って認証をかけても良いと思います。私は この記事 を参考に認証の設定を行いましたが,問題なく動作しました。

さて,今回とても簡単に動いた Jenkins ですが,このままでは実運用には適していません。

最大の問題は, Cloud Foundry 環境のファイルシステムが揮発性である (永続的ではない) ということです。

Cloud Foundry のアプリケーションのインスタンスは,コンテナーの中で動作します。コンテナーはアプリケーションのインスタンスが起動するたびに作成され,停止されたり再起動がかかったりしたら廃棄されます。この時,コンテナー内のファイルも全て消えてしまいます。

Jenkins は通常,設定等をファイルに保存するので,再起動がかかると全て設定が消えてまっさらの状態に戻ってしまいます。これは Jenkins だけでなく,ファイルシステムを利用するアプリケーション全てに共通の問題です。なお,Jenkins の設定の問題に関しては, Database plugin という,設定をデータベースに保存する Jenkins プラグインを使うと解決できる可能性がありますが,今回は試していません。ご要望があれば検証して別に記事を書くかもしれません。

もう一つ,今回は slave を使わない master のみの構成で試したので正確なことはわかっていませんが,Jenkins には master と slave との通信の問題もありそうです。Jenkins では build を本体とは別のマシン (slave) で行う機能がありますが,Cloud Foundry 上で Jenkins の master / slave を動作させる場合,再起動がかかるたびにコンテナーが再作成され,それらは再起動前とは異なるホスト/ポートで待ち受けることになるので,master と slave はお互いが待ち受けるホスト/ポートの情報をなんらかの手段で共有するか,外部に公開されたURL経由でのみアクセスを行うかするなどの考慮が必要になりそうです。この点が実際に問題になるのかどうかもわかっていないのですが,これもご要望があれば試してみるかもしれません。

さて,上述のような制約がある中,いったい Cloud Foundry 上で Jenkins を動かすことにどのような意味があるのでしょうか。個人的には「新しいプラグインを試したい」「新しいジョブを試したい」「Jenkins をアップグレードする前に既存ジョブが動作するかどうか試したい」というような,試しに使う新しいインスタンスを起動する方法として適しているのではないかと思います。

Jenkins は apt や yum などのパッケージ・マネージャーでも簡単に入りますし,DockerHub から Docker Image として起動することもできます。しかし,自分の環境を汚さず,かつ極めて簡単に起動できるという点で,お試し Jenkins を作るための選択肢の一つであると考えています。

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

2015-06-29

Node-RED を Cloud Foundry で動かす


本日の第18回「Cloud Foundry 百日行」は Node-RED です。

[Node-RED] 基本情報


  • 公式サイト
    http://nodered.org/
  • ソースコード
    https://github.com/cloudfoundry-community/node-red-cf-ready.git
  • 参考
    https://www-304.ibm.com/connections/blogs/et/entry/node-red
    【参考日本語記事】 http://www.infoq.com/jp/news/2014/06/ibm-node-red-qconlondon

Node-RED は IBM 英国のHursley研究所で開発されたデジタル社会に対応したツールです。2014年に公開され、オープンソースになっています。最近、IFTTT がはやっていますが、これは様々な情報源からデータを入手、加工し、別の情報に出力するというものです。Node-RED も同じように様々な情報源のデータを取得、加工するツールです。IFTTT のエンジニア向け版といってもよいかと思います。昨今、様々なデバイスがつながる Internet of Things 対応や 様々な API を駆使したサービス結合が必要になってきていますが、Node-RED ではそうしたアプリをGUIで直感的に作成できるようにしてくれます。

今回は、Node-REDを Cloud Foundry ベースの PaaS にデプロイして利用する方法、およびNode-REDの簡単な動作についてご紹介したいと思っています。

デプロイ

1. ソースの入手


今回は、Cloud Foundry Community 版を利用します。git clone でソースを入手します。

$ git clone https://github.com/cloudfoundry-community/node-red-cf-ready.git

2. Cloud Foundry へデプロイ


Cloud Foundry として Bluemix を利用しました。Node-RED は Node.js ランタイムで動作します。

$ cf push amntnodered


Bluemix のため Node ビルドパックがカスタマイズされていますが、Cloud Foundry Foundation 版 Node.js ビルドパックでも動作します。正常にデプロイできるとアプリケーションにアクセスできるようになるでしょう。



Node-RED の簡単な説明


アプリケーションURLを開くと Node-RED エディターが開きます。左側にあるのがパレットで
node と呼ばれる様々な部品があります。情報の入力、加工、および出力に利用します。この node は開発者が追加できます。



中央にあるのがフローエディターで、ここが開発の中心となります。左側にあるパレットから node を選択して配置します。




右側はnode の説明、およびデバッグコンソールです。例えば、"email" の node はどのようにすれば電子メールが送信できるかの説明が出てきます。




それではいくつか動かしてみましょう。

Node-RED を動かしてみる

1. Twitter をモニターするフローの作成


最初に Twitter メッセージをモニターするフローを作成してみます。左側のパレットに social/twitter, output/debug の node があるのでそれらをシートに配置し線でつなぎます。


次に、twitter node をダブルクリックします。ここで自身の Twitter アカウントを入力します。今回は適当なハッシュタグを設定してみました。


DEPLOY ボタンが右上にあるので、それをクリックします。



しばらくすると指定したハッシュタグでメッセージが出てくるはずです。




2. Twitter メッセージをメールするフローの作成


デバッグだけでは簡単なので、Twitterメッセージをメールしてみます。debug node を削除して、代わりに e-mail node を配置します。


e-mail の node には適切なアカウント情報を入力します。ここでは Google のメールサービスを利用してみました。なお、アプリケーションとしてアクセスするので、セキュリティを多少ゆるく設定する必要があるようです。パスワードがうまく入らないケースがあるようなので、一時的に簡単なパスワードに変更して試験する必要がありました。しばらくするとメールが飛んできました。






3. 最近の地震をGoogle Map に表示するフローの作成


さて、Node-RED にはコミュニティーがあり、http://flows.nodered.org/ という場所に様々なフローや部品が公開されています。その中の、"gmaps experiment + earthquake experiment" を試してみます。

先ほどの Twitterフローは削除してしまいます (control+Aで全体選択、DELETEキーで削除)。"gmaps experiment + earthquake experiment" の URL: http://flows.nodered.org/flow/52ed7bb0d7b349472dee にフローがあるので、これをコピーし、右上にあるメニューから IMPORT->Clipboard を選択します。



Paste するとフローを配置できるようになります。



DEPLOY ボタンをクリックして、http://<app-url>/map (例: http://amntnodered.mybluemix.net/map) を開きます。全世界の最新地震情報が Google社の提供する地図サービスにマッピングされているのが表示されるでしょう。なおこのフローでは U.S. Geological Survey ( http://earthquake.usgs.gov/ ) が提供する情報をNode-RED で加工処理するようになっているようです。



4. その他の情報、重要な注意事項


https://github.com/node-red アカウントにはデフォルト以外の node がいくつか公開されています。

  • https://github.com/node-red/node-red-web-nodes
    Google カレンダーサービスの利用や Flickr 写真サービスなどのWEBサービスへのアクセス。

  • https://github.com/node-red/node-red-nodes
    Raspberry PiやBeaglebone などのハードウェアを取扱う node やちょっとしたユーティリティ。
     
  • http://flows.nodered.org/
    コミュニティーが開発した node やフロー
Node-RED でスマートホンからメールを出すと同時にカレンダーに追加するなどのフローがかけるかもしれませんね。

注意事項

 今回紹介した Node-RED のフローエディターの内容はローカルファイルシステムに書かれるようになっていますので、アプリケーションの明示的な停止や Cloud Foundry インフラのメンテナンスによってコンテナが再起動すると消えてしまいます。重要なフローがある場合には、Export 機能を利用してバックアップを取得してください。なお、完成したフローがある場合には、Export したフローを flows.json ファイルに保存し、コマンド起動時のパラメータとして渡すとコンテナ再起動でも完成したフローを読み込んでくれます。詳細はドキュメントを参照してください。

おまけ


筆者のまわりでは、Node-RED が少しはやっています。もともと Node-RED は Internet of Things 向けに作られているので、趣味にて Raspberry Piに接続したカメラからの画像をアップロードして、人が認識された場合に警告するシステムを作っていました。iPhone からの情報を処理するシステムを開発している人もいます。また、WEBシステムをプロトタイピングするのにも向いているので、ハッカソンで有効活用されているようです。様々な可能性をひめているツールですので、ぜひ試してみてください。




今回の環境

  • cf-release (v205)  (IBM Bluemix)
  • Node-RED
    https://github.com/cloudfoundry-community/node-red-cf-ready/tree/7c286187a071c9f9327e4f94ec0356d88e7b2c2f

2015-06-26

SQL Buddy を Cloud Foundry で動かす

本日の第17回「Cloud Foundry 百日行」は、 SQL Buddy です。
このアプリケーションはMySQLの操作をブラウザ上で実行するPHPアプリです。
これまで紹介したアプリにおいてもcf-mysql-releaseのMySQLを度々利用しましたが、MySQLにテーブルの作成や初期データの入力などが必要になった際にデータベースの中身が見れないのはちょっと不便です。そんな時にこのアプリを利用すればデータベースの中身を見ながら作業が進められます。

基本情報

デプロイ

手順
  • 0) 準備
  • 1) アプリの起動
  • 2) 動作確認

0.準備

まずはソースコードの取得からですが、バージョンを指定してダウンロードは出来なさそうなので公開されているものをダウンロードします。
この時のバージョンは1.3.3(Jan 18, 2011)です。
$ wget https://github.com/calvinlough/sqlbuddy/raw/gh-pages/sqlbuddy.zip
$ unzip sqlbuddy.zip
$ cd sqlbuddy
sqlbuddy$ ls
ajaxcreatetable.php  ajaxsavecolumnedit.php  config.php      edit.php    functions.php  includes    LICENSE   query.php  themes
ajaxfulltext.php     ajaxsaveedit.php      css      edituser.php  home.php   index.php   locale   README  users.php
ajaximportfile.php   ajaxsaveuseredit.php    dboverview.php  export.php    images   insert.php  login.php   serve.php
ajaxquery.php      browse.php       editcolumn.php  exports    import.php   js       logout.php  structure.php

1.アプリの起動

cf push を実行する前に 百日行記事 第10回 にあったように php-buildpack のオプション設定用ディレクトリと設定ファイルを作成しMySQLモジュールを読み込めるようにします。
sqlbuddy$ mkdir .bp-config/
sqlbuddy$ vi .bp-config/options.json
{
    "PHP_EXTENSIONS": ["mysql"]
}
これで準備完了。
アプリを --no-start オプションを付けて cf push し、これまで同様に cf-mysql-release で作成したMySQLのデータベース接続情報が cf env で確認できるところまで実行します。
sqlbuddy$ cf push sqlbuddy -b https://github.com/cloudfoundry/php-buildpack.git --no-start
sqlbuddy$ cf create-service p-mysql 100mb-dev app1-db
sqlbuddy$ cf bind-service sqlbuddy app1-db
sqlbuddy$ cf env sqlbuddy
Getting env variables for app sqlbuddy in org k-nagai / space work as k-nagai...
OK

System-Provided:
{
 "VCAP_SERVICES": {
  "p-mysql": [
   {
    "credentials": {
     "hostname": "10.244.1.18",
     "jdbcUrl": "jdbc:mysql://10.244.1.18:3306/cf_e5edadbd_37d9_4427_8b43_242df820e262?user=4LqkSI6cUfnzRjvf\u0026password=1PuiNgg1J02ITGhP",
     "name": "cf_e5edadbd_37d9_4427_8b43_242df820e262",
     "password": "1PuiNgg1J02ITGhP",
     "port": 3306,
     "uri": "mysql://4LqkSI6cUfnzRjvf:1PuiNgg1J02ITGhP@10.244.1.18:3306/cf_e5edadbd_37d9_4427_8b43_242df820e262?reconnect=true",
     "username": "4LqkSI6cUfnzRjvf"
    },
    "label": "p-mysql",
    "name": "app1-db",
    "plan": "100mb-dev",
    "tags": [
     "mysql"
    ]
   }
  ]
 }
}

次にアプリを起動します。
sqlbuddy$ cf start sqlbuddy
:
OK

requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: sqlbuddy.10.244.0.34.xip.io
last uploaded: Tue Jun 23 07:38:27 +0000 2015
stack: lucid64

     state     since                    cpu    memory          disk      details   
#0   running   2015-06-23 04:39:15 PM   0.0%   23.2M of 256M   0 of 1G      
デプロイ完了です。

2.動作確認

ではブラウザでアクセスしましょう。
ログイン画面が表示されるので cf env で得た接続情報を入力します。
今回の場合は上から”hostname”,”username”,”password”の順で入力。

ログインしたらこんな感じに表示されるので好みの Language を選んで利用して下さい。

データベースの操作は左のツリーの DATABASES よりデータベース名を選択します。

後は最上部のメニューにてQueryでSQLコマンドの入力かImportでSQLファイルの読み込み、またはGUIでテーブル作成などを行っていきます。
なおcf-mysql-releaseで提供されるMySQLではすべての操作が出来るわけではないのでテーブル作成やデータの挿入、データの確認程度で利用して下さい。

おまけ

今回の SQL Buddy はCloud Foundryで利用する場合、単体で使用するというよりは他のアプリでcf-mysql-releaseのMySQLを使う時に初期設定や確認で利用するケースが想定されます。
その為、今回行った手順のように SQL Buddy 用のMySQLを作成するケースは少なく、他のアプリ用に作成したMySQLにバインドしてログインするといった手順になります。
また極端に言えば、SQL Buddy とMySQLをバインドして接続情報を得なくても、他のアプリとMySQLの接続情報を利用すればログイン可能です。
しかし、データベースとの接続情報をブラウザでやり取りするのは”いかがなものか”といった場合はこんな方法があります。
まずlogin.phpを下記のように編集します。
sqlbuddy$ cp login.php login.php.org
sqlbuddy$ vi login.php
sqlbuddy$ diff login.php.org login.php
18a19
> /*
22c23,29
< 
---
> */
> $services = getenv("VCAP_SERVICES");
> $services_json = json_decode($services,true);
> $mysql_config = $services_json["p-mysql"][0]["credentials"];
> $host = $mysql_config["hostname"];
> $user = $mysql_config["username"];
> $pass = $mysql_config["password"];
編集内容は元々の”ログイン情報”が記載してある箇所をコメントアウトし、VCAP_SERVICESで取得した情報を設定するように変更しています。
編集した SQL Buddy を先に紹介した手順で cf push してアクセスしたいMySQLのServiceにバインドしてから cf start します。
こうするとブラウザにアクセスした段階で既に該当のデータベースにログインした状態になります。
MySQLの作業が必要なくなればバインドを解除することでアクセスが出来なくなります。
また他のMySQLのServiceのデータベースの作業がしたくなった場合は、そのMySQLのServiceにバインドして cf restage するだけで利用可能です。

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

2015-06-24

Angular-Invoicing を Cloud Foundry で動かす

本日の第16回「Cloud Foundry 百日行」は、AngularJS製のWeb請求書システム Angular Invoicing です。Webでの請求書とはどういうものなのでしょうか? さっそく見て行きましょう。

基本情報

ソースコードの取得

$ git clone https://github.com/metaware/angular-invoicing.git
$ cd angular-invoicing/
$ ls
css  images  index.html  js  README.md

ディレクトリ内には、 index.htmljs/ などが入っています。となると、この百日行のブログでも 第5回 以降、度々登場してきた staticfile-buildpack を使うことで間違いなさそうですね。

アプリのpush

ではこれまでにならって、まずは staticfile-buildpack を指定してpushしてみましょう。

$ cf push invoicing -b https://github.com/cloudfoundry-incubator/staticfile-buildpack.git
Creating app invoicing in org ueno / space test1 as ueno...

:

0 of 1 instances running, 1 down
0 of 1 instances running, 1 down
0 of 1 instances running, 1 down
0 of 1 instances running, 1 down
0 of 1 instances running, 1 down
0 of 1 instances running, 1 starting
0 of 1 instances running, 1 starting
0 of 1 instances running, 1 starting
0 of 1 instances running, 1 starting
0 of 1 instances running, 1 starting
0 of 1 instances running, 1 starting
0 of 1 instances running, 1 starting
0 of 1 instances running, 1 starting
0 of 1 instances running, 1 starting
0 of 1 instances running, 1 down
0 of 1 instances running, 1 failing
FAILED
Start unsuccessful

TIP: use 'cf logs invoicing --recent' for more information

デプロイ失敗です。
最後の”TIP”が示す通り、 cf logs invoicing --recent でログを確認してみると、以下のようにあります。

2015-06-23T17:46:41.86+0900 [App/0]      ERR /home/vcap/app/nginx/sbin/nginx: error while loading shared libraries: libssl.so.1.0.0: cannot open shared object file: No such file or directory

え? libssl.so.1.0.0 が無い?
環境的な疑いがあるとすると、指定したbuildpackですね。つい最近まで問題無く動いていたおなじみの staticfile-buildpack ですが、もしかして、何か変更が入ってないでしょうか? 念の為、確認してみましょう。

過去の百日行記事を振り返ると、6/15付けの 第8回 ではこのbuildpackが用いられて問題無く動作していたようです。
https://github.com/cloudfoundry/staticfile-buildpack/commits/master
から、最近のcommitをチェックしてみると、それ以降に以下の3件のcommitが積まれています。

  • https://github.com/cloudfoundry/staticfile-buildpack/commit/d00d45d43dcdb3bfa75b1445533c6fda5035ef3b

  • https://github.com/cloudfoundry/staticfile-buildpack/commit/f09f720bfa4e52f4ed65c5e27b92a133b4eeeafa

  • https://github.com/cloudfoundry/staticfile-buildpack/commit/871e635532b31b523f526ae386846c54d4220458

このうち上の2つは動作に影響を与えないテキスト・ファイル等の修正なので、実質的に何かありそうなcommitは最後のみ。
最後のcommitはサブモジュール・ポインターの変更なので、サブモジュールを見てみます。
サブモジュール・ポインターの変更対象の間 ( 0b1eb13f9a747494b0abac8c665bb556cd07c749f752ecf4b27d2f31bb082dfe7a47c76fefc769d7 ) に積まれたcommitは以下の4つ:

  • https://github.com/cloudfoundry-incubator/compile-extensions/commit/f752ecf4b27d2f31bb082dfe7a47c76fefc769d7

  • https://github.com/cloudfoundry-incubator/compile-extensions/commit/70f6c1674e6fee7e0b8a72a466c1fcc907df444c

  • https://github.com/cloudfoundry-incubator/compile-extensions/commit/7f91e7f3a5b50ee1a426e4d2a8c6bffb592a6d25

  • https://github.com/cloudfoundry-incubator/compile-extensions/commit/1b9f66b9a280488947175fa1f9221b2e45ac381d

順次見ていくと、 3番目のコミット で stack のデフォルトが lucid64cflinuxfs2 に変更されています。
この修正は当然依存ライブラリーの処理にも影響すると考えられます。
このコードを読む限り、これを変更前の lucid64 に戻すには、環境変数 CF_STACKlucid64 を指定しさえすればいいはず。早速試してみましょう。

$ cf set-env invoicing CF_STACK lucid64
Setting env variable 'CF_STACK' to 'lucid64' for app invoicing in org ueno / space test1 as ueno...
OK
TIP: Use 'cf restage' to ensure your env variable changes take effect

“TIP”が言うように、 cf restage で環境変数指定後のデプロイを確認してみましょう。

$ cf restage invoicing
Restaging app invoicing in org ueno / space test1 as ueno...
-----> Downloaded app package (76K)
-----> Downloaded app buildpack cache (4.0K)
Cloning into '/tmp/buildpacks/staticfile-buildpack'...
Submodule 'compile-extensions' (https://github.com/cloudfoundry-incubator/compile-extensions.git) registered for path 'compile-extensions'
Cloning into 'compile-extensions'...
Submodule path 'compile-extensions': checked out 'f752ecf4b27d2f31bb082dfe7a47c76fefc769d7'
grep: Staticfile: No such file or directory
-----> Using root folder
-----> Copying project files into public/
-----> Setting up nginx
grep: Staticfile: No such file or directory
-----> Uploading droplet (2.3M)

1 of 1 instances running

App started


OK

App invoicing was started using this command `sh boot.sh`

Showing health and status for app invoicing in org ueno / space test1 as ueno...
OK

requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: invoicing.10.244.0.34.xip.io
last uploaded: Tue Jun 23 10:14:53 +0000 2015
stack: lucid64

     state     since                    cpu    memory         disk      details   
#0   running   2015-06-23 07:18:45 PM   0.0%   3.4M of 256M   0 of 1G      

デプロイが成功し、アプリが起動しました!

動作確認

URL http://invoicing.10.244.0.34.xip.io にアクセスしてみます。

初期画面

初期画面にアクセスできました。請求書の画面そのものですね。

入力

請求書の項目毎に入力できます。
単価と数量が決まると自動で価格が入ります。
右上のロゴを消すこともでき、正式な請求書そのものに仕上がってきました。

請求書発行

プリントモードにすると、不要なボタンとかも消え、請求書イメージが表示されます。
実際にプリントプレビューすると、以下の請求書ができました。

なるほど、機密性の高い請求書情報ではありますが、ボランティア団体とか、比較的小さ目の組織がLAN内で共有しながら簡便に請求書発行するのに使えそうですね。

まとめ

今回は簡単にデプロイできると思いきや、環境に落とし穴がありました。
使用しているcf-releaseはv194。このデフォルトのstackは lucid64 です。ところが、v207でそれが cflinuxfs2 に変更になりました。
それに合わせて、 staticfile-buildpack の方も、 cflinuxfs2 をデフォルトサポートするように変更されました。
このstackの食い違いによって、最初エラーが出たので、 lucid64staticfile-buildpack が動くように、環境変数設定で対処しました。

では今回もデプロイに必要最低限なmanifestファイルを作成しておきましょう。

$ vi manifest.yml
applications:
- name: angular-invoicing
  buildpack: https://github.com/cloudfoundry/staticfile-buildpack
  env:
    CF_STACK: lucid64

cf push だけでデプロイができることを確かめてみてください。

ペーパーレスが進む昨今、今回は請求書のデジタル化の原型のようなアプリでした。認証もDBも無い極めてシンプルなアプリですが、それはそれで、請求書のような固い文書でも使い方次第でWebで気軽に扱えるようになるということですね。

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

WonderCMS を Cloud Foundry で動かす

本日の第15回「Cloud Foundry 百日行」は、WonderCMSです。
謳い文句は the smallest CMS in the world ということで、百日行ラインナップの中にもいくつかあるCMSアプリの第一歩としてチャレンジしてみます。
ちなみにCMSとは Content Management System の略で、Webサイトなどのコンテンツの構成要素(テキスト、イメージetc)を管理してくれるソフトウェアの事です。

WonderCMS基本情報

デプロイ

手順

  • 0) 準備
  • 1) アプリの起動
  • 2) 動作確認

0.準備

まずはいつものようにソースコードの取得から。
今回はソースコードがgithubリポジトリ上に無いため公式サイトのZIP形式の物を取得してきましょう。

$ wget http://wondercms.com/download/beta/wondercms-0.6-BETA.zip
$ unzip wondercms-0.6-BETA.zip 
$ cd wondercms
wondercms$ ls
editText.php  files  index.php  js  plugins  themes

1.アプリの起動

さて、公式サイトによればこのアプリは展開→アップロードでセットアップが終了するそうです。smallestを自負するだけのことはあります。
展開はすでに終わってしまっているので早速アップロード、この場合はCloud Foundryへのデプロイをしてみましょう。

wondercms$ cf push wondercms
(一部略)
Creating app wondercms in org ukaji / space default as ukaji...
OK

Using route wondercms.10.244.0.34.xip.io
Binding wondercms.10.244.0.34.xip.io to wondercms...
OK

Uploading wondercms...
Uploading app files from: /home/ukaji/workspace/wondercms
Uploading 16.2K, 12 files
Done uploading               
OK

Starting app wondercms in org ukaji / space default as ukaji...
-----> Downloaded app package (12K)
-------> Buildpack version 1.0.2
Use locally cached dependencies where possible
 !     WARNING:        No composer.json found.
       Using index.php to declare PHP applications is considered legacy
       functionality and may lead to unexpected behavior.
       See https://devcenter.heroku.com/categories/php
-----> Setting up runtime environment...
       - PHP 5.5.12
       - Apache 2.4.9
       - Nginx 1.4.6
-----> Installing PHP extensions:
       - opcache (automatic; bundled, using 'ext-opcache.ini')
-----> Installing dependencies...
       Composer version ac497feabaa0d247c441178b7b4aaa4c61b07399 2014-06-10 14:13:12
       Warning: This development build of composer is over 30 days old. It is recommended to update it by running "/app/.heroku/php/bin/composer self-update" to get the latest version.
       Loading composer repositories with package information
       Installing dependencies
       Nothing to install or update
       Generating optimized autoload files
-----> Building runtime environment...
       NOTICE: No Procfile, defaulting to 'web: vendor/bin/heroku-php-apache2'

-----> Uploading droplet (64M)

1 of 1 instances running

App started


OK

App wondercms was started using this command `vendor/bin/heroku-php-apache2`

Showing health and status for app wondercms in org ukaji / space default as ukaji...
OK

requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: wondercms.10.244.0.34.xip.io
last uploaded: Mon Jun 22 10:15:27 +0000 2015
stack: lucid64

     state     since                    cpu    memory          disk      details   
#0   running   2015-06-22 07:16:04 PM   0.0%   92.6M of 256M   0 of 1G   

すぐに起動してくれました。

2.動作確認

それでは、動作確認です。
いつものようにブラウザでアクセスをします。

特にエラーが出ることもなく動いています。
最初は特にやることもないので早速右下から Login を押してログインしてみましょう。
デフォルトのPasswordは「admin」です。

ログインをしても一見何が変わったのかという感じなのですが、よくよく見ると上の方に Setting という項目が追加されています。

試しに「PaaS」というページを作るためにこのような状態でNavigationの項目にある click here to refresh を押してみましょう。
すると一通り更新が反映され、新しく作った「PaaS」のページが右上から編集できるようになります。
各ページではコンテンツをHTMLで編集することができます。

Webページの作成ノウハウが無くても比較的簡単にWebページを作れる便利ツール、といったところでしょうか。

おまけ

さて、今回のWonderCMSですが、シンプルなだけあってCloud Foundry上に非常に簡単にデプロイすることができました。
しかし実はこのアプリ、Databaseが不要というシンプルな構造が影響し、このままCloud Foundry上で運用するには気に留めておかなければいけない点があります。

突然ですが、Cloud Foundry上のアプリには「永続性」が存在しません。つまり、アプリは永続的な状態を保持してくれないため、もし再起動がかかった場合などは初期状態に戻ることを意識しておく必要があります。
論より証拠ということで、実際にやってみましょう。
先ほど編集をした状態から、アプリケーションを再起動してみます。

wondercms$ cf restart wondercms

(一部略)

requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: wondercms.10.244.0.34.xip.io
last uploaded: Mon Jun 22 23:40:34 +0000 2015
stack: lucid64

     state     since                    cpu    memory          disk      details   
#0   running   2015-06-23 01:16:43 PM   0.0%   92.4M of 256M   0 of 1G

再起動が完了しました。
URLに再びアクセスしてみると・・・

作成した項目などが消えてしまい、初期状態に戻っているのがわかります。

では、Cloud Foundry上で動作する全てのものは永続的な状態を保持できないのか、というと、もちろんそんなことはありません。
普段からCloud Foundryをご利用の方、百日行の記事をお読み頂いている方はすでにお気づきかも知れませんが、「アプリの状態」を保存しておきたい場合には、過去の記事でも何度か触れられている「Service」という機能を使えばOKです。

※参考:現在の環境で利用できるService一覧

wondercms$ cf marketplace
Getting services from marketplace in org ukaji / space default as ukaji...
OK

service      plans                     description   
PostgreSQL   Basic PostgreSQL Plan*    PostgreSQL on shared instance.   
p-mysql      100mb-dev, 1gb-dev        A MySQL service for application development and testing   
p-redis      shared-vm, dedicated-vm   Redis service to provide a key-value store

(環境に登録されているServiceを利用する以外にもUserprovided Serviceを用いるなどの方法も存在します。)

今回のようなCMSを例に挙げるならば、「ページの編集履歴を保存しておきたい」「ユーザの登録情報を保存しておきたい」などは別途用意したServiceに保存しておく、というような形になるでしょう。
そのように設計されたアプリであれば、再起動を行ってもServiceに保存された情報は失われることなく取り出すことが可能となります。

DatabaseをServiceとして利用したCMSアプリに関しては、また後日ご紹介したいと思います。

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

2015-06-23

Yabitz を Cloud Foundry で動かす

本日の第14回「Cloud Foundry 百日行」は、Yabitzです。
社内のサーバなどホスト管理を行えるアプリケーションです。rubyで書かれており、加えてMySQL環境が必要となります。

[Yabitz]基本情報

デプロイ

手順

  • 0) 準備
  • 1) cf-mysql-releaseを利用する為のコード修正
  • 2) アプリの起動
  • 3) 動作確認

0.準備

まずはソースコードの取得をしましょう。

$ git clone https://github.com/livedoor/yabitz.git
$ cd yabitz
$ ls
config.ru  Gemfile  lib  public  README.md  scripts  spec  tmp  view

ここでデプロイに入る前に補足を少ししておきます。

  • これまでの記事にも出てきましたがMySQLなどのDBと連携が必要となるアプリではDBの初期設定が必要なものが多く存在します。
    今回のアプリもスクリプトでデータベースのスキーマを作成する必要があります。
    cf create-service で作成したMySQLのDBに初期設定を行う場合、「アプリ内から初期設定を実行する」または「DB初期設定用のアプリを利用する」などいくつかの対処がありますが、今回は「アプリ内から初期設定を実行する」方法で対処しています。機会があればその他の方法もご紹介したいと思います。
  • このアプリはユーザデータを扱う方法がpluginで提供されています。今回はホストの情報を管理するDBにユーザ情報も管理する為のpluginを利用します。
  • 今回紹介する方法でアプリをデプロイする為にはGemfile.lockファイルを bundle install で作成する必要があります。その為、下記の準備が必要になります。
    • ruby(利用したバージョン 2.1.5)
    • bundler(利用したバージョン 1.10.2)

1.cf-mysql-releaseを利用する為のコード修正

まずはアプリを停止状態で cf push してMySQLとバインドできる状態にします。

$ cf push yabitz --no-start

そしてMySQLを準備します。
なおMySQLはこれまでの記事にも何度か出てきているcf-mysql-releaseを利用します。

$ cf marketplace

service      plans                     description   
p-mysql      100mb-dev, 1gb-dev        A MySQL service for application development and testing   

$ cf create-service p-mysql 100mb-dev yabitzdb
$ cf bind-service yabitz yabitzdb
$ cf env yabitz
System-Provided:
{
 "VCAP_SERVICES": {
  "p-mysql": [
   {
    "credentials": {
     "hostname": "10.244.1.18",
     "jdbcUrl": "jdbc:mysql://10.244.1.18:3306/cf_9f086cff_c59f_4b6f_afa7_925ce372764b?user=k3i8E0ZSj6aBmlLx\u0026password=HMHe7pf0XLqw2j0c",
     "name": "cf_9f086cff_c59f_4b6f_afa7_925ce372764b",
     "password": "HMHe7pf0XLqw2j0c",
     "port": 3306,
     "uri": "mysql://k3i8E0ZSj6aBmlLx:HMHe7pf0XLqw2j0c@10.244.1.18:3306/cf_9f086cff_c59f_4b6f_afa7_925ce372764b?reconnect=true",
     "username": "k3i8E0ZSj6aBmlLx"
    },
    "label": "p-mysql",
    "name": "yabitzdb",
    "plan": "100mb-dev",
    "tags": [
     "mysql"
    ]
   }
  ]
 }
}
:

準備が終われば手元のコードの修正に入ります。

MySQLとの接続情報は上記の cf env で得た値をベタ書きしてもいいのですが、環境変数 VCAP_SERVICES(以下 環境変数) から情報を取得できるようにコードを一部書き換えます。
まず環境変数はjsonで提供される為、Gemfileに以下のように追記しjsonを利用できるようにします。

$ vi Gemfile
$ git diff
diff --git a/Gemfile b/Gemfile
index a217b6e..426bc22 100644
--- a/Gemfile
+++ b/Gemfile
@@ -8,6 +8,6 @@ gem 'haml'
 gem 'sass'
 gem 'ruby-ldap'
 gem 'rspec'
-
+gem 'json'
 gem 'passenger'
 gem 'unicorn'

次に手元の環境で bundle install します。これは後述のruby-buildpackの適用条件を満たす為にGemfile.lockを作成をすることが目的ですのでこちらのリポジトリのコードを使う場合は不要です。
なお、 bundle install でのエラーは自己解決していただくか、修正済みのコードをご利用ください。

$ bundle install --path vendor/bundle
$ cat Gemfile.lock
GIT
  remote: git://github.com/tagomoris/stratum.git
  revision: d763f84f3885a81bad263588f3f8e62a58d73b6f
  specs:
    stratum (0.1.0)
      mysql2-cs-bind

GEM
  remote: http://rubygems.org/
  specs:
    diff-lcs (1.2.5)
    haml (4.0.6)
      tilt
    json (1.8.3)
    kgio (2.9.3)
    mysql2 (0.3.18)
    mysql2-cs-bind (0.0.6)
      mysql2
    passenger (5.0.10)
      rack
      rake (>= 0.8.1)
    rack (1.6.2)
    rack-protection (1.5.3)
      rack
    raindrops (0.13.0)
    rake (10.4.2)
    rspec (3.3.0)
      rspec-core (~> 3.3.0)
      rspec-expectations (~> 3.3.0)
      rspec-mocks (~> 3.3.0)
    rspec-core (3.3.0)
      rspec-support (~> 3.3.0)
    rspec-expectations (3.3.0)
      diff-lcs (>= 1.2.0, < 2.0)
      rspec-support (~> 3.3.0)
    rspec-mocks (3.3.0)
      diff-lcs (>= 1.2.0, < 2.0)
      rspec-support (~> 3.3.0)
    rspec-support (3.3.0)
    ruby-ldap (0.9.17)
    sass (3.4.14)
    sinatra (1.4.6)
      rack (~> 1.4)
      rack-protection (~> 1.4)
      tilt (>= 1.3, < 3)
    tilt (2.0.1)
    unicorn (4.9.0)
      kgio (~> 2.6)
      rack
      raindrops (~> 0.7)

PLATFORMS
  ruby

DEPENDENCIES
  haml
  json
  mysql2
  mysql2-cs-bind
  passenger
  rspec
  ruby-ldap
  sass
  sinatra
  stratum!
  unicorn

BUNDLED WITH
   1.10.2
$ rm -rf vendor/bundle

cf push 後にruby-buildpackにて 再度 bundle install は実行されるので、不要となるvendor/bundleディレクトリは削除しておいて下さい。

次はMySQLの環境変数を読み込めるように3つのファイルを編集します。

  • アプリとDBの接続plugin(lib/yabitz/plugin/config_instant.rb)
    requireに先ほどGemfileに追加したjsonを加え、接続情報を環境変数から取得できるように変更します。

  • 利用するユーザデータを指定するplugin(lib/yabitz/plugin/instant_membersource.rb)
    cf create-service で作成したMySQL内のユーザデータのtableを利用する為にpluginを有効化します。

  • DBの初期設定スクリプト(scripts/db_schema.rb)
    上記のpluginにはDBの初期設定スクリプトと別に初期ユーザ登録用スクリプト(instant/register_user.rb)が準備されています。
    しかし初期ユーザ登録用スクリプトは対話型となっておりCloud Foundry環境で実行するには不向きです。
    その為、初期ユーザ登録機能もバッチ型のDBの初期設定スクリプトにまとめています。

$ vi lib/yabitz/plugin/config_instant.rb
$ vi lib/yabitz/plugin/instant_membersource.rb
$ vi scripts/db_schema.rb
$ git diff

:

diff --git a/lib/yabitz/plugin/config_instant.rb b/lib/yabitz/plugin/config_instant.rb
index 15b6462..b67cb61 100644
--- a/lib/yabitz/plugin/config_instant.rb
+++ b/lib/yabitz/plugin/config_instant.rb
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-
+require 'json'
 module Yabitz::Plugin
   module InstantConfig
     def self.plugin_type
@@ -18,14 +18,14 @@ module Yabitz::Plugin
     end
 
     DB_PARAMS = [:server, :user, :pass, :name, :port, :sock]
-
+    mysql_dbs = JSON.parse(ENV['VCAP_SERVICES'])
     CONFIG_SET = {
       :database => {
-        :server => 'localhost',
-        :user => 'root',
-        :pass => nil,
-        :name => 'yabitz_instant',
-        :port => nil,
+        :server => mysql_dbs["p-mysql"][0]["credentials"]["hostname"],
+        :user => mysql_dbs["p-mysql"][0]["credentials"]["username"],
+        :pass => mysql_dbs["p-mysql"][0]["credentials"]["password"],
+        :name => mysql_dbs["p-mysql"][0]["credentials"]["name"],
+        :port => mysql_dbs["p-mysql"][0]["credentials"]["port"],
         :sock => nil,
       },
       :test_database => {
diff --git a/lib/yabitz/plugin/instant_membersource.rb b/lib/yabitz/plugin/instant_membersource.rb
index 5f8b9a6..6e4ddff 100644
--- a/lib/yabitz/plugin/instant_membersource.rb
+++ b/lib/yabitz/plugin/instant_membersource.rb
@@ -2,6 +2,7 @@
 
 require 'digest/sha1'
 require 'mysql2-cs-bind'
+require 'json'
 
 module Yabitz::Plugin
   module InstantMemberHandler
@@ -9,13 +10,14 @@ module Yabitz::Plugin
       [:auth, :member]
     end
     def self.plugin_priority
-      0
+      1
     end
 
-    DB_HOSTNAME = "localhost"
-    DB_USERNAME = "root"
-    DB_PASSWORD = nil
-    DATABASE_NAME = "yabitz_member_source"
+    mysql_dbs = JSON.parse(ENV['VCAP_SERVICES'])
+    DB_HOSTNAME = mysql_dbs["p-mysql"][0]["credentials"]["hostname"]
+    DB_USERNAME = mysql_dbs["p-mysql"][0]["credentials"]["username"]
+    DB_PASSWORD = mysql_dbs["p-mysql"][0]["credentials"]["password"]
+    DATABASE_NAME = mysql_dbs["p-mysql"][0]["credentials"]["name"]
     TABLE_NAME = "list"
     def self.query(sql, *args)
       result = []
diff --git a/scripts/db_schema.rb b/scripts/db_schema.rb
index a1fce02..727b511 100644
--- a/scripts/db_schema.rb
+++ b/scripts/db_schema.rb
@@ -2,6 +2,17 @@
 # -*- coding: utf-8 -*-
 
 require 'mysql2'
+require 'digest/sha1'
+
+## default user data
+TABLE_NAME = "list"
+USERNAME = "admin"
+PASSWORD = "password"
+FULLNAME = "default_adminuser"
+MAIL = ""
+BADGE = ""
+POSITION = ""
+PASSHASH = Digest::SHA1.hexdigest("#{PASSWORD}")
 
 # before require of schema.rb
 #  init.rb MUST be already loaded with $YABITZ_RUN_ON_TEST_ENVIRONMENT = true
@@ -351,6 +362,22 @@ removed     ENUM('0','1')   NOT NULL DEFAULT '0'
 ) ENGINE=InnoDB charset='utf8'
 EOSQL
 
+       sqls.push <<-EOSQL
+CREATE TABLE #{TABLE_NAME} (
+id          INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
+name        VARCHAR(64)     NOT NULL UNIQUE KEY,
+passhash    VARCHAR(40)     NOT NULL,
+fullname    VARCHAR(64)     NOT NULL,
+mailaddress VARCHAR(256)    ,
+badge       VARCHAR(16)     ,
+position    VARCHAR(16)
+) ENGINE=InnoDB charset='utf8'
+EOSQL
+
+       sqls.push <<-EOSQL
+INSERT INTO #{TABLE_NAME} SET name='#{USERNAME}',passhash='#{PASSHASH}',fullname='#{FULLNAME}',mailaddress='#{MAIL}',badge='#{BADGE}',position='#{POSITION}'
+EOSQL
+
     c = conn()
     sqls.each do |s|
       c.query(s)

2.アプリの起動

今回のアプリには複数のbuildpackを利用しています。

  • heroku-buildpack-apt
    指定のパッケージを apt-get install できる Buildpackになります。
    今回は ruby-buildpack にて実行される bundle install で発生するエラー( ruby-ldap の gem install )を回避する為に libsasl2-dev のパッケージを追加します。

  • ruby-buildpack
    rubyのアプリをデプロイする為のBuildpackです。
    このBuildpackは下記のように bundle install を実行してくれます。
    bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment
    ただし、Gemfile.lockが無い状態で実行すると --deployment オプションが指定されている為、エラーとなってしまいます。その為、先ほどの手順のようにGemfile.lockを事前に作成しておく必要があります。

そして最後に複数のBuildpackを適用する為に下記のBuildpackを利用します。  

  • heroku-buildpack-multi
    通常一つしか適用できないBuildpackを複数用いる為のBuildpackです。
    (補足)heroku-buildpack-multiは非常に便利なBuildpackですが、利用するBuildpackによってはheroku-buildpack-multiで正常に動作をしないものもあるので注意が必要です。

それぞれのBuildpackに必要なファイルを準備していきます。
まずはheroku-buildpack-aptに必要なAptfile。 cf push を実行するアプリのルートディレクトリに作成します。
ここで作成するAptfileには apt-get install したいパッケージ名を記載します。

$ echo "libsasl2-dev" > Aptfile

次にheroku-buildpack-multiに必要な.buildpacks。こちらも上記のAptfileと同じディレクトリに作成します。
ここで作成する.buildpacksには利用したいBuildpackを実行したい順番で記載します。今回はruby-buildpackで実行される bundle install の前に libsasl2-dev パッケージの追加が完了している必要があるので以下の順番になります。

$ echo -e "https://github.com/ddollar/heroku-buildpack-apt.git\nhttps://github.com/cloudfoundry/ruby-buildpack.git" > .buildpacks
$ cat .buildpacks 
https://github.com/ddollar/heroku-buildpack-apt.git
https://github.com/cloudfoundry/ruby-buildpack.git

Buildpackの準備はここまでです。

いよいよデプロイに移ります。

cf push に際し注意いただきたいのは初回と2回目以降で-cオプションに変更があります。
初回はDBの初期設定スクリプトを指定して実行する必要がありますが、2回目以降は設定済みのため不要です。
もしmanifest.ymlを作成される場合はその点を考慮して下さい。今回は作成せずに進めます。

  • 初回
$ cf push yabitz -b https://github.com/ddollar/heroku-buildpack-multi.git -c 'bundle exec ruby scripts/db_schema.rb&&bundle exec rackup config.ru --port=$PORT'
  • 2回目以降
$ cf push yabitz -b https://github.com/ddollar/heroku-buildpack-multi.git -c 'bundle exec rackup config.ru --port=$PORT'

では cf push を実行。

$ cf push yabitz -b https://github.com/ddollar/heroku-buildpack-multi.git -c 'bundle exec ruby scripts/db_schema.rb&&bundle exec rackup config.ru --port=$PORT'
:
App started


OK

App yabitz was started using this command `bundle exec ruby scripts/db_schema.rb&&bundle exec rackup config.ru --port=$PORT`

Showing health and status for app yabitz in org k-nagai / space work as k-nagai...
OK

requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: yabitz.10.244.0.34.xip.io
last uploaded: Fri Jun 19 01:13:12 +0000 2015
stack: lucid64

     state     since                    cpu    memory          disk      details   
#0   running   2015-06-19 10:14:45 AM   0.0%   65.1M of 256M   0 of 1G      

これでアプリのデプロイ完了です。

3.動作確認

URL( yabitz.10.244.0.34.xip.io )にアクセスしてみましょう。
画面の上にある”ログイン”をクリックしてログイン(db_schema.rbに記載したユーザ情報)します。

あとは各情報を登録して管理をするのですが、ホスト登録を達成できるようになるまでに各リストの準備がなかなかに大変です。
たとえ登録ボタンをクリックして「Internal Server Error」が出ても「アプリケーションがうまく動いていない!」なんてことは考えずに「どこかのリストの登録が先に必要なんだ」と思って進めてください。
ブラウザの横に cf logs を表示しながら作業を進めると、どのテーブルの情報でエラーを起こしているかがわかり効率がいいです。

$ cf logs yabitz

登録出来た時は達成感が少し生まれます。資源管理は大変だ!ということですかね。
もう少しアプリの入力チェックにコードを加えればいきなりInternal Server Errorが返されることもなくなるかもしれませんが、今回はここまでです。お疲れさまでした。

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

2015-06-22

Agar.io を Cloud Foundry で動かす

本日の第13回「Cloud Foundry 百日行」は、Agar.ioのクローンです。
このアプリケーションもゲームアプリですので、ぜひデプロイをして遊んでみてください。
ちなみにこのアプリはNode/JavaScript製となっています。

Agar.io基本情報

デプロイ

手順

  • 0) 準備
  • 1) アプリの起動
  • 2) 動作確認

0.準備

まずはいつものようにソースコードの取得から。

$ git clone https://github.com/huytd/agar.io-clone
$ cd agar.io-clone
agar.io-clone$ ls
bower.json  client  gulpfile.js  LICENSE  manifest.yml  package.json  README.md  server

Readmeのインストール手順を見てみると、何とこのアプリ、IBM Bluemixへのデプロイをサポートしているようです。
IBM BluemixがCloud FoundryをベースにしているPaaSなこともあり、確かにアプリのディレクトリの中身をよくよく見てみると見覚えのある内容の manifest.yml ファイルがすでに用意されています。
IBM Bluemix環境へのデプロイをお試しの方はReadmeを読んでいただくとして、この記事ではbosh-lite環境へのデプロイに挑戦してみましょう。

1.アプリの起動

さて、アプリのReadmeによるとこのアプリの起動手順は

  • Step1) npm install で依存ライブラリのインストール
  • Step2) node server/server.js もしくは npm start でサーバ起動

となっています。これさえ無事に終えれば http://localhost:3000 にアクセスすることでゲームがプレイできるようですね。

Cloud Foundryにアプリをデプロイする時、実は上記のStep1はCloud Foundryが(※正確に言うとCloud Foundry上でNodeJSのためのBuildpackが)自動でやってくれます。
Step2についてですが、このアプリを起動するためのコマンド、 node server/server.js についてはデプロイを行う人がCloud Foundryに教えてあげましょう。

実際にやってみます。

agar.io-clone$ mv manifest.yml manifest.yml.bluemix
agar.io-clone$ cf push agar-clone -b https://github.com/cloudfoundry/nodejs-buildpack -c "node server/server.js"
(一部略)
-----> Uploading droplet (17M)

1 of 1 instances running

App started


OK

App agar-clone was started using this command `node server/server.js`

Showing health and status for app agar-clone in org ukaji / space default as ukaji...
OK

requested state: started
instances: 1/1
usage: 512M x 1 instances
urls: agar-clone.10.244.0.34.xip.io
last uploaded: Thu Jun 18 02:19:19 +0000 2015
stack: lucid64

     state     since                    cpu    memory          disk      details   
#0   running   2015-06-18 11:20:29 AM   0.0%   46.3M of 512M   0 of 1G

IBM BluemixもCloud Foundryをベースにしているため、実はmanifestファイルについてもそのまま利用できてしまうケースが多いのですが、今回は残念ながらそのままではデプロイが失敗してしまうため、別の起動コマンドかmanifestファイルが必要となります。(失敗の理由について後ほど触れます。)
ここでは、そのままpushを行うとIBM Bluemix用に書かれたmanifestファイルを読んでしまうため、ファイルをリネームして使わないようにしておきました。
実際のデプロイに必要なのはその次にある cf push 〜 の1行です。中々に長いログが流れますが、無事に起動してくれました。

さて、今回のデプロイに使った cf push のオプション -c ですが、これはアプリの起動コマンドを指定できるオプションです。
今回のアプリのように起動をするコマンドを明示的に指定する必要がある場合に使用します。
今回のようなNodeJSのアプリ起動時の node 〜 や、Rubyアプリ起動時の bundle exec 〜 などで用いられることが多いです。

2.動作確認

それでは、動作確認を行いましょう。
いつものようにブラウザでアクセスをします。

無事起動しているようです。
ユーザ名を決めてプレイしてみましょう。

皆でプレイするゲームにも関わらず「Players: 1」表示なのが少々物悲しいですがともかく無事にデプロイができました。
ゲームの遊び方/ルールは

  • マウスの動きに追従して自分のキャラクター(=ボール)を動かす
  • 自分より小さなボールや他プレイヤーは、衝突をして吸収することができる
  • 逆に自分より大きな他キャラクターに衝突されると吸収されてしまう
  • 自分のキャラクターの大きさは、どれだけ吸収をしたかで決定する

こんなところでしょうか。他にも吸収度合いによって移動速度が低下したりといろいろな制約があるようですが、いずれにせよ他プレイヤーを排除するのがゲームの目的のようです。
・・・一人で遊ぶゲームではないですね。

おまけ

第11回の記事で、次のような内容をご紹介しました。

「わざわざBuildpackを指定しなくても、現在の環境に標準で入っているBuildpackならば自動的に動かすことができる」

実は今回の環境にもNodeJSのBuildpackが標準で入っているので、わざわざBuildpackを指定する必要もないように思えます。
しかし今回のケースでは、Buildpackの特定・実行開始までは上手く行ってくれていたのですが、残念なながら、実行途中でエラーを吐いて失敗してしまいました。

どうやらこれは、Buildpackのバージョンに起因する問題のようです。
Buildpackも日々開発が進められているため、あるバージョンで動いたものが別のバージョンでは動かないというのは大いにありうる話です。
一度デプロイに成功したアプリが動かなくなってしまった時などは、この問題を疑って見るのも一つの手かもしれません。

最後に、折角IBM Bluemix用のBuildpackがあるので、Cloud Foundry用のmanifestファイルも追記しておきます。
今回の事例に学び、バージョン指定付きでgithubのリポジトリからBuildpackを取得してくるような記述をしてみましょう。

agar.io-clone$ vi manifest.yml
---
applications:
- name: agar-clone
  memory: 128M
  disk_quota: 256M
  buildpack: https://github.com/cloudfoundry/nodejs-buildpack#19b6bc8c15aac2b159a14fc7d9928247447bf8f6
  command: node server/server.js

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

2015-06-19

Etherpad を Cloud Foundry で動かす

Etherpad 基本情報

  • 公式サイト
    http://etherpad.org/
  • ソースコード
    https://github.com/ether/etherpad-lite
  • 関連情報
    https://en.wikipedia.org/wiki/Etherpad

Etherpad とは?

Etherpad は日本ではあまりなじみがないかもしれませんが、複数の開発者がよってたかって文章を編集できるソフトウェアで、オープンソースです。文書を校正したい場合には、文書のレビュー機能を使って電子メールでまわすというのはよく実施されていると思いますが、ちょっとした文書を少しレビューしてほしい場合には、Etherpad はうってつけです。なおこのソフトウェアは Google によって会社が買収された後にオープンソース化されたようですね。

それでは動かしてみましょう。

デプロイ

今回はデプロイに Bluemix を利用しましたが、独自機能は利用していないので、Cloud Foundry でも動作すると思います。

1. ソースの入手

今回は Etherpad-lite を導入します。ソースは GitHub で公開されています。


% git clone https://github.com/ether/etherpad-lite
Cloning into 'etherpad-lite'...
remote: Counting objects: 26649, done.
remote: Total 26649 (delta 0), reused 0 (delta 0), pack-reused 26649
Receiving objects: 100% (26649/26649), 18.94 MiB | 180.00 KiB/s, done.
Resolving deltas: 100% (18848/18848), done.
Checking connectivity... done.
% cd etherpad-lite/
% ls
CHANGELOG.md     LICENSE   README.md  doc                     src        tests
CONTRIBUTING.md  Makefile  bin        settings.json.template  start.bat  var


GitHub のページにローカルの環境で動作させるための手順が書いてあります。それによると "bin/run.sh" を動かせばよいとあります。今回は、Cloud Foundry 上で動作させるため、このコマンドを実施しないで、その内容を Cloud Foundry で実現するための修正を行います。

2. Cloud Foundry 上で動作させるための修正

Ehterpad-lite は Node.js で稼働するアプリケーションです。Node.js アプリケーションをCloud Foundry で動かすための重要なポイントは:
  • 固定ポートを指定している場合には、PORT環境変数を読み取るように修正する
  • シンボリックリンクを利用しないようにファイル・ディレクトリ(フォルダー)情報を修正する
  • package.json ファイルを用意する
があります。Etherpad-lite も上記を修正する必要がありました。

固定ポートですが、Etherpad-lite は固定ポートを指定していない場合には、PORT環境変数を読み取ってくれるようです。したがって、固定ポートを指定している settings.json.template を書き換えます。

% diff settings.json.template.original settings.json.template
16c16
<   "port" : 9001,
---
>   // "port" : 9001,


次に、"bin/run.sh" の中身をみると "bin/installDeps.sh" ではシンボリックリンク作成処理とnpm コマンド実行行があるので、これを "cp -r "とnpm コマンド実行行をコメントアウトします。


% cp installDeps.sh installDeps.sh.original
% vi installDeps.sh
% diff installDeps.sh.original installDeps.sh
78c78
<   [ -e ep_etherpad-lite ] || ln -s ../src ep_etherpad-lite
---
>   [ -e ep_etherpad-lite ] || cp -r ../src ep_etherpad-lite
80c80
<   npm install --loglevel warn
---
> #  npm install --loglevel warn


npmコマンドをコメントアウトするのは、Cloud Foundryへアプリケーションを "push"するときに自動的に行ってくれるようにするためです。package.json は src フォルダーにあるものを再利用できます。


% cp src/package.json .


installDeps.sh を実行して、必要なファイル (ただし npm パッケージは除く)を入手します。jQueryなどのプラグインを入手するようです。


% bin/installDeps.sh
Copy the settings template to settings.json...
Ensure that all dependencies are up to date...  If this is the first time you have run Etherpad please be patient.
Ensure jQuery is downloaded and up to date...
Clearing minified cache...
Ensure custom css/js files are created...

3. Cloud Foundryにアプリケーションをプッシュ。

準備ができたら、Cloud Foundry へプッシュします。ここでは installDeps.sh でコメントアウトした npm installを実行します。今回は Bluemix を使うため Bluemix にログインします。

% cf login -a https://api.ng.bluemix.net
login: <bluemix-id>
password: <bluemix-password>
% cf push etherpad-lite -c "cd node_modules/ep_etherpad-lite; npm install ; cd ../../; node node_modules/ep_etherpad-lite/node/server.js"

     state     since                    cpu    memory           disk          details
#0   running   2015-06-17 10:55:23 AM   0.0%   125.3M of 256M   97.9M of 1G
%


正常にプッシュできたらアプリケーションは稼働中というメッセージが出てくるでしょう。 本来であれば "npm install" もスキップできるように工夫できると思いますが、 まだそこまでソースの修正ができませんでした。なお Bluemixの利用についてはここを参照してください。

4. 動作確認



動作を確認してみましょう! アプリケーションのURLを開きます。


新規作成ボタンをクリックすると。新しい画面に移動します。指定された URLを 他の人と共有することで、協同作業ができるようになります。



たとえば二人が作業すると入力メッセージの色がかわりお互いどのように作業しているか わかるようになります。



5. その他、注意事項等

今回は説明していませんが、データベースには Cloud Foundry がサポートしている "MySQL"を使うことができます。 情報を破棄してもよいのであれば、このままで良いのです が、破棄されては困る!といった場合には MySQL データベースを利用した方がよいでしょう。

また、"cf push" 時には Node.js のビルドパックを指定していません。この場合、Bluemix が提供する Node.js ビルドパックが使われます。Bluemix が提供する Node.js ビルドパックは Cloud Foundry が提供するビルドパックを含み、独自の拡張をしています。もし気になる場合には、"cf push -b" にて Cloud Foundry のビルドパックを指定してもよいと思います。


余談



実は、Etherpad-lite の Cloud Foundry 版が Cloud Foundry Foundation の コミュニティー に作成されています(ココをクリック)。

今回は、あえてオリジナルの Etherpad-lite を使ったわけですが、この記事を読んで 頂ければ、どのように既存の Node.js アプリケーションを Cloud Foundry で稼働させる ように移植できるか?について大まかにご理解いただけたのではないかと思っております。

今回の環境

  • cf-release (v205)  (IBM Bluemix)
  • etherpad-lite
    https://github.com/ether/etherpad-lite/tree/a0aa9470a383e5361e544a9ba76fad06f69fd628


2015-06-18

chatapp を Cloud Foundry で動かす

本日の第11回「Cloud Foundry 百日行」は、Pythonで書かれたチャットアプリ chatapp です。デプロイしてチャットを楽しんでみましょう。

基本情報

ソースコードの取得

$ git clone https://github.com/vinceprignano/chatapp.git

chatappディレクトリに入ります。

$ cd chatapp/

アプリのpush

今回はデータベースも使っていないシンプルなPythonのチャットアプリ。まずはそのままpushしてみましょう。

$ cf push chatapp
Creating app chatapp in org ueno / space test1 as ueno...

:

途中、Pythonの環境構築が走り、デプロイが進んで行き、、


:

requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: chatapp.10.244.0.34.xip.io
last uploaded: Wed Jun 17 06:14:50 +0000 2015
stack: lucid64

     state     since                    cpu    memory        disk      details   
#0   running   2015-06-17 03:16:46 PM   0.0%   70M of 256M   0 of 1G  

そのままデプロイが成功し、アプリが起動しました!

動作確認

何はともあれ、起動したアプリ、まずはそのURL http://chatapp.10.244.0.34.xip.io にアクセスしてみます。

初期画面(ユーザーエントリー)

名前を入れてエントリーします。

チャット画面

複数人でエントリーしてチャットしてみましょう。
リアルタイムにチャットを楽しめますね。

まとめ

pushコマンド一発! 今回はCloud Foundryならではの簡便さを楽しめましたね。

ところで、今回のアプリはPythonが使われているので、python-buildpack が必要なはずです。これはどのように処理されていたのでしょうか?
答えは、使用しているbosh-lite環境にそのbuildpackが既に標準で入っているのです。確認してみましょう。

$ cf buildpacks
Getting buildpacks...

buildpack          position   enabled   locked   filename
java_buildpack     1          true      false    java-buildpack-v2.5.zip
ruby_buildpack     2          true      false    ruby_buildpack-offline-v1.1.4.zip
nodejs_buildpack   3          true      false    nodejs_buildpack-offline-v1.0.4.zip
go_buildpack       4          true      false    go_buildpack-offline-v1.0.4.zip
python_buildpack   5          true      false    python_buildpack-offline-v1.0.5.zip
php_buildpack      6          true      false    php_buildpack-offline-v1.0.2.zip

もしお使いの環境にpython-buildpackが入っていなければ、アプリのpushの際に、 -b https://github.com/cloudfoundry/python-buildpack を指定してください。あるいは、第5回の最後で触れたように、manifestファイルに書き込んでおいてもいいですね。

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

2015-06-17

b2evolution を Cloud Foundry で動かす

本日の第10回「Cloud Foundry 百日行」は、b2evolutionです。
多言語複数ユーザー対応のブログb2evolutionはphpで書かれており、加えてMySQL環境が必要となります。

[b2evolution]基本情報

デプロイ

手順

  • 0) 準備
  • 1) アプリの起動
  • 2) DBのインストーラーによる初期設定
  • 3) 動作確認

0.準備

まずはソースコードの取得をしましょう。
github上から取得する場合はこちら
公式サイトからも圧縮ファイルで取得可能。

github上から取得する場合はtagでstable版のものを確認してcheckoutして下さい。
今回は5.2.2のstable版を利用します。

$ git clone https://github.com/b2evolution/b2evolution.git
$ cd b2evolution
$ git tag -l
$ git checkout 5.2.2
b2evolution$ ls
blogs  bower.json  doc  gettext  Gruntfile.js  index.de-DE.html  index.fr-FR.html  index.html  index.pt-BR.html  
index.ru-RU.html  index.src.html  package.json  readme.md  Templates  tests

今回のアプリをデプロイする前に参考サイトにも記載したインストールマニュアルを確認していきます。
手順を簡単にいうと下記の通り

  • 1) ファイルをダウンロードしてblogsディレクトリをFTPでWEBサーバにアップロード
  • 2) MySQLを準備
  • 3) サイト/install/index.phpにアクセスしてDBのインストールを実行

ここで重要となるのはblogsディレクトリ以外のファイルはデプロイに使用しないということと、
DBの初期設定をサイト経由で行うので事前のDBのセットアップが不要であることです

1.アプリの起動

ではCloud Foundry上にアプリをデプロイしてみましょう。

b2evolution$ cd blogs

上記ではまず公式サイトのインストールマニュアルどおりデプロイするblogsディレクトリに移動します。
そしてMySQLの接続情報を得る為に一旦–no-startオプションをつけてアプリをプッシュします。

b2evolution/blogs$ cf push b2evo -b https://github.com/cloudfoundry/php-buildpack.git --no-start

そしてMySQLを準備します。
なお今回利用するMySQLは#003 EtherSheetでも紹介したcf-mysql-releaseを利用します。

b2evolution/blogs$ cf marketplace

service      plans                     description   
p-mysql      100mb-dev, 1gb-dev        A MySQL service for application development and testing   

b2evolution/blogs$ cf create-service p-mysql 100mb-dev b2evodb
b2evolution/blogs$ cf bind-service b2evo b2evodb
b2evolution/blogs$ cf env b2evo
System-Provided:
{
 "VCAP_SERVICES": {
  "p-mysql": [
   {
    "credentials": {
     "hostname": "10.244.1.18",
     "jdbcUrl": "jdbc:mysql://10.244.1.18:3306/cf_a40fd514_30ba_427a_87c0_e413f61d21e2?user=0AmHUBPfncwD7MKp\u0026password=kcCByptiOfyqavRC",
     "name": "cf_a40fd514_30ba_427a_87c0_e413f61d21e2",
     "password": "kcCByptiOfyqavRC",
     "port": 3306,
     "uri": "mysql://0AmHUBPfncwD7MKp:kcCByptiOfyqavRC@10.244.1.18:3306/cf_a40fd514_30ba_427a_87c0_e413f61d21e2?reconnect=true",
     "username": "0AmHUBPfncwD7MKp"
    },
    "label": "p-mysql",
    "name": "b2evodb",
    "plan": "100mb-dev",
    "tags": [
     "mysql"
    ]
   }
  ]
 }
:

(参考)上記コマンドは以下の通り。

  • cf marketplace) MySQLが利用できる環境なのか、planとして何が提供されているかの確認
  • cf create-service <利用するサービス名> <プラン名> <作成するサービスに付与する名前>) サービスの作成
  • cf bind-service <アプリ名> <サービス名>) アプリとサービスの関連付け
  • cf env <アプリ名>) 環境情報

ここまで準備が出来たら今回はバインドしたサービスの接続情報を環境変数でアプリに受け渡す為の編集を行います。

このアプリはデプロイ後にDB初期設定においてMySQLへの接続情報をブラウザから入力することになるのですが、その際の接続情報の初期値はconf/_basic_config.phpから渡されています。
そこで下記の方法でファイルを編集し接続情報を受け渡します。

以下はMySQLの接続情報を各変数に入力している箇所の後に環境変数から取得した値を上書きする設定を追記しています。

b2evolution/blogs$ cp conf/_basic_config.template.php conf/_basic_config.php
b2evolution/blogs$ vi conf/_basic_config.php
b2evolution/blogs$ diff conf/_basic_config.template.php conf/_basic_config.php 
61a62,69
> $services = getenv("VCAP_SERVICES");
> $services_json = json_decode($services,true);
> $mysql_config = $services_json["p-mysql"][0]["credentials"]; 
> 
> $db_config['user'] = $mysql_config["username"];
> $db_config['password'] = $mysql_config["password"];
> $db_config['name'] = $mysql_config["name"];
> $db_config['host'] = $mysql_config["hostname"];

上記の追記した箇所は環境により少し違う箇所があるので”cf envの出力結果”にあわせて下さい。

ここまで出来たら次に.bp-config/options.jsonを作成します。

b2evolution/blogs$ mkdir .bp-config/
b2evolution/blogs$ vi .bp-config/options.json
{
    "PHP_EXTENSIONS": ["mysql"]
}

これは今回利用しているPHP Buildpackのオプション設定用ディレクトリと設定ファイルになります。

実はこの作業についてはエラーの先回り対処になっています。
このファイルを作成せずに進むとPHPにMySQLのモジュールが読み込まれていない状態となりDBの初期設定時にエラーが発生します。

MySQL error!
The PHP MySQL module could not be loaded.
Error: dl(): Dynamically loaded extensions aren't enabled
You probably have to edit your php configuration (php.ini) and enable this module (mysql.so).
Do not forget to restart your webserver (if necessary) after editing the PHP conf.

その為、PHPにMySQLモジュールの追加する対応を行っています。

ここまで来たら再度ファイルをプッシュするだけです。

b2evolution/blogs$ cf push b2evo -b https://github.com/cloudfoundry/php-buildpack.git

:
requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: b2evo.10.244.0.34.xip.io
last uploaded: Mon Jun 15 06:46:54 +0000 2015
stack: lucid64

     state     since                    cpu    memory          disk      details   
#0   running   2015-06-15 03:51:52 PM   0.0%   27.3M of 256M   0 of 1G      

上記のようなログが見えればデプロイ成功です。

2.DBのインストーラーによる初期設定

b2evo.10.244.0.34.xip.ioにブラウザでアクセスしてみます。

インストールの実行を促されるのでメッセージのいちばん下にあるhereいずれか(どちらも同じところに転送されます)をクリックします。

ここで設定したMySQLの環境変数がうまくとれていれば_basic_config.phpの設定は成功です。
とれていない場合は再度編集し直してアプリをデプロイし直すか、あきらめてcf envの情報を手入力して下さい。

問題なければ”Update config file”ボタンをクリックします。

ここでは初期設定なので”New install”を選択し”Go!”をクリックします。

ここでエラーが発生します。

実はこの画面ではいくつかの設定のチェックを行うプロセスが設定されており、そのうちの一つにアプリのURLに外部(Internet上)からアクセス可能なのかを自動チェックする機能が入っています。しかしbosh-lite環境はプライベートIPアドレス(10.*.*.*)を利用しているので外部からのアクセスが出来ずにエラーが返されてしまいます。
これについては正しく外部からアクセスできるCloudFoundry環境であればエラーが発生しないことが確認できている為、今回のbosh-lite環境ではエラーを無視して進めます。

次は “Continue installation»” をクリックします。

DBの初期設定が動き出します。

login情報が表示されたら完了です。

3.動作確認

管理画面にアクセスしましょう。
先のログイン情報の上にある”login”をクリックして管理画面に入ります。

好きなように設定してみて下さい。
その後、再度b2evo.10.244.0.34.xip.ioにブラウザでアクセスしてみます。

ちゃんとブログが出来上がっています。
好きな言語で構築できるようなので試してみて下さい。

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

2015-06-16

MindMup を Cloud Foundry で動かす

「Cloud Foundry 百日行」第9回目です。
今日のアプリは,MindMup です。

基本情報

MindMup は,mind map を書くためのツールです。 README では,「最も生産的な mind-mapping 環境を作ることが目標」と書かれています。

記事の概要は以下の通りです。

  1. ソースコードの取得
  2. デプロイ
  3. 動作確認に際して解決した問題
  4. 動作確認

ソースコードの取得

まずはいつも通りソースコードの取得から。GitHub から git でソースコードを clone してきます。

$ git clone https://github.com/mindmup/mindmup.git

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

$ cd mindmup/

デプロイ

このアプリは Heroku 上での動作を想定して作られているため,同じ buildpack という仕組みを利用する Cloud Foundry 上でも,極めて簡単にデプロイできました。

$ cf push mindmup
Creating app mindmup in org nota-ja / space 100 as nota-ja...
......
requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: mindmup.10.244.0.34.xip.io
last uploaded: Mon Jun 15 09:43:54 +0000 2015
stack: lucid64

     state     since                    cpu    memory          disk      details
#0   running   2015-06-15 06:44:33 PM   0.0%   49.1M of 256M   0 of 1G

動作確認に際して解決した問題

アプリの push まではすんなりいったのですが,動作確認を始ようとした際に2つの問題に遭遇したので,その解決方法について述べます。

最初の問題: Google Analytics アカウント

このアプリは,production モードで実行される時には,Google Analytics のアカウントが必須です。アカウントをお持ちの方は,環境変数 GOOGLE_ANALYTICS_ACCOUNT に ID をセット してください。設定方法は,

$ cf set-env mindmup GOOGLE_ANALYTICS_ACCOUNT <Google Analytics の ID>

です。設定を有効にするために,restage が必要になります。

$ cf restage mindmup

しかし,今回の動作確認では Google Analytics のアカウントを使わずに本アプリを動作させる方法として,環境変数 RACK_ENVproduction 以外の値に設定する方法をとりました。同じく設定後に restage が必要です。

$ cf set-env mindmup RACK_ENV development
$ cf restage mindmup

2番目の問題: JavaScript ライブラリーの読み込み失敗

以前はこれで問題なく動作したのですが,今回記事を書くにあたって再検証したところ,さらに別の問題 〜 特定の JavaScript ライブラリーの読み込みに失敗する 〜 に遭遇しました。

原因を調べた結果,このコミット 以降にこの問題が発生していることがわかりました。そこで web.rbstatic_ts の値をこのコミットが入る前の値に戻す修正を 現時点のmaster に対して行ったところ,なんとか正常に操作できるようになりました。

以下はそのコード差分です。コミット自体は, こちら にあります。

diff --git a/web.rb b/web.rb
index 27faf22..9267821 100644
--- a/web.rb
+++ b/web.rb
@@ -20,7 +20,7 @@ def cache_last_news
   end
 end
 configure do
-  static_ts = '20150316155124'
+  static_ts = '20140912202404'
   public_host = ENV['PUBLIC_HOST'] || 'http://static.mindmup.net'
   set :earliest_supported_ios_version, (ENV["EARLIEST_IOS_VERSION"] && ENV["EARLIEST_IOS_VERSION"].to_f) || 1
   set :static_host, "#{public_host}/#{static_ts}"

これが正しい対処方法ではなさそうな気もしますが,今回は時間の都合上このままで進めます。

動作確認

これで動く状態になったので,動作確認していきます。
なお私の環境では本アプリは (通常動作確認に使っている) Safari では正常に動作しなかったので,今回の動作確認は全て Chrome で行いました。

初期画面

ブラウザーからアクセスすると,最初は以下のような画面が出ます。

新規 mind map

【Create a new map】 → 【Public online map to share with the world】を選択します(他のオプションは別途サービスのアカウントやサブスクリプションが必要です)。

Mind map の描画

右手のツール・ペインを利用して,mind map を描きます。

日本語もOKです。

Mind map のエクスポート/インポート

描いた mind map をローカルファイルにエクスポート/インポートすることもできました。

【エクスポート】

【インポート】

Google Drive のアカウントをお持ちの方は,それを使えばもっと簡単に保存/取り出しができると思います。

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

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