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

2015-09-18

lojinha を Cloud Foundry で動かす

「Cloud Foundry 百日行」第64日目は、Play Framework ベースのネットショッピング用アプリ lojinha です。アプリ名が見慣れない単語だったため調べてみたところ、どうもポルトガル語のようです。実際にショッピングサイトとして利用する場合は、英語等に翻訳する必要があるかもしれませんが、Play Framework のアプリをCloud Foundry で動かしてみたかったのでやってみました。

基本情報

デプロイ準備から動作確認までの手順は以下の通りです。

  • 1) Play 用ツールのインストール
  • 2) デプロイ準備
  • 3) デプロイ
  • 4) 動作確認

1. Play 用ツールのインストール

まず、Cloud Foundry へデプロイするバイナリを作成するため、デプロイ実行環境に Play用ツールの Activator をインストールします。
lojinhaのソースをみると、Play Frameworkのバージョンは 2.3.8 あたりが良さそうなので、それに対応する Activator_1.3.5 をDLページから取得してきます。
JDK 6 以降が必要なので予め準備しておいてください。

$ wget https://downloads.typesafe.com/typesafe-activator/1.3.5/typesafe-activator-1.3.5-minimal.zip
$ unzip typesafe-activator-1.3.5-minimal.zip
$ ls activator-1.3.5-minimal
activator  activator.bat  activator-launch-1.3.5.jar

解凍先を PATH へ登録し、 activator コマンドが実行できるようにします。

$ export PATH="$HOME/activator-1.3.5-minimal:$PATH"
$ activator --version
sbt launcher version 0.13.8

2. デプロイ準備

まずは、lojinha が PostgreSQL を使用するため、 PostgreSQL のサービスを作成しておきます。
もしデプロイする bosh-lite 環境に PostgreSQL サービスブローカがない場合、 百日行の「postgresql-cf-service-broker を Cloud Foundry で動かす」を参考に、事前に準備をしてください。

lojinha$ cf create-service PostgreSQL "Basic PostgreSQL Plan" lj-pg
lojinha$ cf services
:
OK

name         service      plan                    bound apps   last operation
lj-pg        PostgreSQL   Basic PostgreSQL Plan                create succeeded

次に、デプロイ用のバイナリを作成するため、 lojinha のソースを取得してきます。

$ git clone https://github.com/jcranky/lojinha.git
$ cd lojinha
lojinha$ ls
app.json  Capfile  config.ru  Gemfile  LICENSE.txt   Procfile  Rakefile  script

activator コマンドでデプロイ用のバイナリを作成します。
Warning が出るかもしれませんが、最後に success がでれば完了です。

lojinha$ activator dist

:
[info]
[success] Total time: 30 s, completed Sep 18, 2015 10:37:47 AM

zip ファイルが target/universal の下に出来ているか確認します。

lojinha$ ls target/universal/
lojinha-1.0-SNAPSHOT.zip  tmp

3. デプロイ

まずは、 no-start 指定でアプリを Push します。

lojinha$ cf push lj-100 --no-start
Creating app lj-100 in org horiu-jn / space 100nichi as horiu-jn...
OK

Creating route lj-100.10.244.0.34.xip.io...
OK

Binding lj-100.10.244.0.34.xip.io to lj-100...
OK

Uploading lj-100...
Uploading app files from: /home/horiu-jn/workspace/apps/lojinha
Uploading 6.4M, 1488 files
Done uploading
OK

次に、サービスをバインドします。

lojinha$ cf bind-service lj-100 lj-pg
Binding service lj-pg to app lj-100 in org horiu-jn / space 100nichi as horiu-jn...
OK
TIP: Use 'cf restage lj-100' to ensure your env variable changes take effect
Creating app lj-100 in org horiu-jn / space 100nichi as horiu-jn...
OK

バインドまで完了したら、 cf env コマンドで VCAP_SERVICES の情報を確認し、バインドした PostgreSQL の ユーザ名、パスワード、データベース名を確認しておきます。
Java アプリ の場合、 DATABASE_URL に格納される URL の形式と異なるため、後ほど作成するアプリデプロイ用の manifest.yml の中でJDBC URL 形式で定義します。

lojinha$ cf env lj-100
:
OK

System-Provided:
{
 "VCAP_SERVICES": {
  "PostgreSQL": [
   {
    "credentials": {
     "uri": "postgres://f7cb3f5f-01a5-4fb9-a13f-1e4c97049cdc:vbburntrrhil3l9i6vrkp6kcta@192.168.15.91:5432/f7cb3f5f-01a5-4fb9-a13f-1e4c97049cdc"
    },
    "label": "PostgreSQL",
    "name": "lj-pg",
    "plan": "Basic PostgreSQL Plan",
    "tags": [
     "PostgreSQL",
     "Database storage"
    ]
   }
  ]
 }
}
:

取得した PostgreSQL の情報を元に、デプロイ用のマニフェストを作成します。

lojinha$ vi manifest.yml
---
applications:
- name: lj-100
  memory: 1G
  path: target/universal/lojinha-1.0-SNAPSHOT.zip
  command: "PATH=$PATH:/home/vcap/app/.java-buildpack/open_jdk_jre/bin ~/lojinha-1.0-SNAPSHOT/bin/lojinha -Dhttp.port=$PORT -DapplyEvolutions.default=true -Ddb.default.driver=org.postgresql.Driver -Ddb.default.url='jdbc:postgresql://192.168.15.91:5432/f7cb3f5f-01a5-4fb9-a13f-1e4c97049cdc?user=f7cb3f5f-01a5-4fb9-a13f-1e4c97049cdc&password=vbburntrrhil3l9i6vrkp6kcta'"

起動時点でメモリを結構使っていたので、 memory: は大きめに指定しています。
command: 部分が長いので、ポイントとなる内容を記述します。

  • コマンド全体は、ダブルクォートで囲みます。
  • java コマンドへのパスが通っていないため、 PATH でコンテナ内でコマンドのある場所へパスを通しています。
PATH=$PATH:/home/vcap/app/.java-buildpack/open_jdk_jre/bin
  • -Dhttp.port には、 $PATH を指定します。
  • -Ddb.default.url には、以下のようなフォーマットでJDBC URL を作成します。URL は必ずシングルクォートで囲んでください。
Ddb.default.url='jdbc:postgresql://<HOST>:<PORT>/<DATABAE>?user=<USER>&password=<PASSWORD>'

デプロイ用のマニフェストが作成できたら、アプリをプッシュします。

lojinha$ cf push

:
OK

requested state: started
instances: 1/1
usage: 1G x 1 instances
urls: lj-100.10.244.0.34.xip.io
last uploaded: Fri Jul 10 10:00:56 UTC 2015
stack: cflinuxfs2
buildpack: java-buildpack=v3.0-https://github.com/cloudfoundry/java-buildpack.git#3bd15e1 open-jdk-jre=1.8.0_45 play-framework-auto-reconfiguration=1.7.0_RELEASE play-framework=2.3.8

     state     since                    cpu    memory       disk      details
#0   running   2015-07-10 07:01:36 PM   0.0%   213M of 1G   0 of 1G

4. 動作確認

ブラウザから、払いだされたアプリのURLへアクセスします。

ログインして、商品情報を追加をしてみます。
URL に /login を指定してログイン画面へアクセスします。
admin の情報は何処にも書いていませんので、lojinha/conf/evolutions/default/1.sql で定義されている情報をもとにログインします。

INSERT INTO _user(email, name, passwd) VALUES('admin@lojinha.com', 'jcranky', '1234');

ログインに成功すると、 admin ページが出てきます。

まず、カテゴリーを追加してみます。
雰囲気で読めますが、 Adicionar categoria がカテゴリー追加画面へのリンクなので、クリックして表示します。

表示されたら、追加するカテゴリー名 (Nome para exibir) と、カテゴリーのURL (Nome para url) を入力し、send (Enviar) をクリックします。 ホーム画面が表示され、追加したカテゴリーが表示されます。

次に、追加したカテゴリーに商品情報を登録します。
admin ページへ戻るリンクは用意されていないため、URLへ直接 /admin を指定して戻ります。
Adicionar item が商品の追加画面へのリンクなので、クリックして表示します。

表示されたら、商品の名前、説明、個数(Lance minimo)、カテゴリを選んで、send (Enviar) をクリックします。
ホーム画面が表示され、追加された商品が表示されます。

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

2015-09-16

WordPress を Cloud Foundry で動かす

「Cloud Foundry 百日行」第62日目。 今回は超メジャーどころのWordPressです。 その為、Cloud Foundryでのデプロイ手順等は沢山あるのでもう紹介の必要なんてないかもしれませんがお付き合いください。

基本情報

手順は以下の通りです。

  • 1) ソースコードの取得
  • 2) アプリのデプロイ
  • 3) 動作確認
  • 4) Cloud Foundry用を利用したデプロイ

1. ソースコードの取得

Cloud Foundryで動作するようにされたものを利用してもいいのですが、それだとすぐに終わってしまうのでまずは公式のソースコードでのデプロイ方法をご紹介します。
まずは日本語ソースコードをダウンロードします。

$ wget https://ja.wordpress.org/wordpress-4.2.4-ja.tar.gz
$ tar xzvf wordpress-4.2.4-ja.tar.gz
$ cd wordpress
$ ls
index.php        wp-blog-header.php    wp-includes        wp-settings.php
license.txt      wp-comments-post.php  wp-links-opml.php  wp-signup.php
readme.html      wp-config-sample.php  wp-load.php        wp-trackback.php
wp-activate.php  wp-content            wp-login.php       xmlrpc.php
wp-admin         wp-cron.php           wp-mail.php

2. アプリのデプロイ

ちなみにご存知でない方の為にお伝えするとWordPressはPHPとMySQLの組み合せで動作させることが出来ます。その為、これまでの記事にも多く登場しているので愛読していただいている方にはおなじみの内容になります。

2.1 PHP拡張モジュールの追加

とりあえずMySQLのモジュールを追加します。

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

2.2 MySQL サービスの準備

$ cf create-service p-mysql 100mb wpdb1

ついでに環境変数から作成したDBとの説情報がとれるように wp-config.php を作成します。

$ cp wp-config-sample.php wp-config.php
$ vi wp-config.php
$ diff wp-config-sample.php wp-config.php 
22a23,27
> 
> $services = getenv("VCAP_SERVICES");
> $services_json = json_decode($services,true);
> $mysql_config = $services_json["p-mysql"][0]["credentials"];
> 
24c29
< define('DB_NAME', 'database_name_here');
---
> define('DB_NAME', $mysql_config["name"]);
27c32
< define('DB_USER', 'username_here');
---
> define('DB_USER', $mysql_config["username"]);
30c35
< define('DB_PASSWORD', 'password_here');
---
> define('DB_PASSWORD', $mysql_config["password"]);
33c38
< define('DB_HOST', 'localhost');
---
> define('DB_HOST', $mysql_config["hostname"]);

2.3 アプリのPush

アプリのプッシュ前にmanifest.ymlを作成します。

$ vi manifest.yml
・・・
$ cat manifest.yml
---
applications:
- name: wpja
  services:
  - wpdb1

では cf push しましょう。

$ cf push
:
requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: wpja.10.244.0.34.xip.io
last uploaded: Thu Aug 6 06:48:30 UTC 2015
stack: cflinuxfs2
buildpack: PHP
 
     state     since                    cpu    memory          disk      details   
#0   running   2015-08-06 03:48:59 PM   1.6%   33.5M of 256M   0 of 1G

ハイ完了!

3. 動作確認

URLにアクセスすれば以下のようなウィザードが上がってくるのでお好きなように入力して下さい。

ログインしてテスト投稿します。


が、ここでアプリを cf restart すると添付ファイルが消失します。

原因は投稿された記事本文はDBに保管されていますが添付ファイルはアプリのローカルに保存される為、 cf restart で見事に消えてしまいます。
ではこれを解消する為にCloud Foundry用に準備されたリポジトリを利用したデプロイを試してみましょう。

4. Cloud Foundry用を利用したデプロイ

まずは同じくソースコードをダウンロード。

$ git clone https://github.com/dmikusa-pivotal/cf-ex-worpress.git
$ cd cf-ex-worpress
$ ls
manifest.yml  README.md  wp-config.php

中身がほとんどありません。実はこのリポジトリには WordPress 自体のソースは含まれていません。
では何が含まれているか見てみましょう。

$ ls -a
.   .bp-config  c  .gitignore    README.md  wp-config.php
..  .cfignore   .git         manifest.yml  .ssh

ここの中で重要なのは .extensions/wordpress/extension.py です。
これは PHP-buildpack のオプションを利用する為のファイルです。これまであまり機会がありませんでしたが、これを利用することで更なるデプロイ内容の拡張が可能となります。
今回はオプションを利用して WordPress のソースコードの取得とアプリの一部のディレクトリに外部サーバのディスクをマウントを行います。後者の機能によりアプリの再起動でリセットされていたデータを残すことが出来ます。

では前準備をしていきます。まずはMySQLを準備します。

$ cf create-service p-mysql 100mb wpdb2

あと環境変数で取得するサービス名が異なるので wp-config.php 修正。

$ vi wp-config.php
$ git diff
diff --git a/wp-config.php b/wp-config.php
index dbbff27..b59be71 100644
--- a/wp-config.php
+++ b/wp-config.php
@@ -16,7 +16,7 @@
  
 // ** Read MySQL service properties from _ENV['VCAP_SERVICES']
 $services = json_decode($_ENV['VCAP_SERVICES'], true);
-$service = $services['cleardb'][0];  // pick the first MySQL service
+$service = $services['p-mysql'][0];  // pick the first MySQL service
  
 // ** MySQL settings - You can get this info from your web host ** //
 /** The name of the database for WordPress */

.bpconfigは既に準備されているので、manifest.ymlを編集。

diff --git a/wp-config.php b/wp-config.php
index dbbff27..b59be71 100644
--- a/wp-config.php
+++ b/wp-config.php
@@ -16,7 +16,7 @@
 
:
 applications:
-- name: mywordpress
-  memory: 128M 
-  path: .
-  buildpack: https://github.com/cloudfoundry/php-buildpack
-  host: wordpress-on
+- name: cfwp
   services:
-  - mysql-db
+  - wpdb2
   env:
-    SSH_HOST: user@your-ssh-server
-    SSH_PATH: /full/or/relative/path/on/ssh/server
-    SSH_KEY_NAME: sshfs_rsa
-    SSH_OPTS: '["cache=yes", "kernel_cache", "compression=no", "large_read"]'
+    SSH_HOST: ubuntu@192.168.1.10
+    SSH_PATH: /home/ubuntu/sshfs
+    SSH_KEY_NAME: id_rsa
+    SSH_OPTS: '["cache=yes", "kernel_cache", "compression=no", "large_read", "Ciphers=arcfour"]'

ここでSSHの接続先サーバ情報と公開鍵の名前などを設定します。

以降はSSH接続の準備になります。
まずはキーを保存するディレクトリを作成し、ディレクトリに権限設定します。

$ mkdir .ssh
$ chmod 700 .ssh
$ ssh-keygen -t rsa -f .ssh/id_rsa
$ ls .ssh/
id_rsa  id_rsa.pub
$ cat .ssh/id_rsa.pub

キーを作成後に接続先のSSHサーバの ssh/authorized_keysに公開鍵(id_rsa.pub)を登録します。
(接続先のSSHサーバ)

$ vi .ssh/authorized_keys

(元のサーバに戻る)

known_hosts に接続先のSSHサーバを記録する為に以下を実行。

$ ssh-keyscan -t rsa 192.168.1.10 > .ssh/known_hosts

で後は cf push といきたいところですがここで 第2回 postgresql-cf-service-broker 記事の「Application Security Group の解放」のとおり接続先のSSHサーバがプライベート・アドレスの場合、接続に失敗します。
その為、過去の記事同様に security group の作成をCloud Foundryの admin 権限で実施します。

$ cf login -u admin
$ vi sg-ssh.json
$ cat sg-ssh.json
[
  {
    "protocol": "tcp",
    "destination": "192.168.1.10",
    "ports": "22"
  }
]
$ cf create-security-group sshwp sg-ssh.json
$ cf logout
$ cf login
(一般ユーザ)

後は cf push するだけですが、折角なので先に利用した日本語版と同じものが入るように一手間加えます。
先ほど登場した extension.py を編集。

$ vi .extensions/wordpress/extension.py
$ git diff
diff --git a/.extensions/wordpress/extension.py b/.extensions/wordpress/extension.py
index 21d6360..5a1bc91 100644
--- a/.extensions/wordpress/extension.py
+++ b/.extensions/wordpress/extension.py
@@ -13,10 +13,10 @@ _log = logging.getLogger('wordpress')
  
  
 DEFAULTS = utils.FormattedDict({
-    'WORDPRESS_VERSION': '4.1.1',  # or 'latest'
+    'WORDPRESS_VERSION': '4.2.4-ja',  # or 'latest'
     'WORDPRESS_PACKAGE': 'wordpress-{WORDPRESS_VERSION}.tar.gz',
     'WORDPRESS_HASH': '258bda90f618d7af3a2db7f22fc926d1fedb06f4',
-    'WORDPRESS_URL': 'https://wordpress.org/{WORDPRESS_PACKAGE}',
+    'WORDPRESS_URL': 'https://ja.wordpress.org/{WORDPRESS_PACKAGE}',
 })

では今度こそ cf push

$ cf push
:
requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: cfwp.10.244.0.34.xip.io
last uploaded: Thu Aug 6 07:42:47 UTC 2015
stack: cflinuxfs2
buildpack: PHP
 
     state     since                    cpu    memory          disk      details   
#0   running   2015-08-06 04:45:23 PM   1.7%   37.2M of 256M   0 of 1G      

動作確認は先ほどと同じ方法で実施。

再起動後も大丈夫。

ついでにSSHサーバのマウントしたディレクトリを確認するとこんな感じ。

~/sshfs$ ls -al
total 32
drwxrwxr-x 6 ubuntu ubuntu 4096 Aug  6 07:43 .
drwxr-xr-x 5 ubuntu ubuntu 4096 Aug  6 07:12 ..
-rw------- 1 ubuntu ubuntu   28 Jan  8  2012 index.php
drwx------ 4 ubuntu ubuntu 4096 Aug  6 07:43 languages
drwx------ 4 ubuntu ubuntu 4096 Aug  6 07:43 plugins
drwx------ 5 ubuntu ubuntu 4096 Aug  6 07:43 themes
drwxrwxr-x 3 ubuntu ubuntu 4096 Aug  6 07:48 uploads
-rw------- 1 ubuntu ubuntu  276 Aug  6 07:43  WARNING_DO_NOT_EDIT_THIS_DIRECTORY

最後にこのSSHで保存する機能はすごくアナログ感はあるのですが、これまでにも紹介したアプリも再起動したら残念な結果がまっているものがあるので、ひとまずこの機能を試してみるのはいかがでしょうか。

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

2015-09-15

PasswordPusher を Cloud Foundry で動かす

「Cloud Foundry 百日行」第61日目は、Ruby-on-Rails ベースの PasswordPusher です。このアプリは、何かのパスワードを遠隔で共有したい場合、Web上で比較的セキュアに簡単に共有することができます。

基本情報

デプロイ準備から動作確認までの手順は以下の通りです。

  • 1) ソースコードの取得
  • 2) デプロイ
  • 3) 動作確認

1. ソースコードの取得

GitHub からソースコードをクローンします。

$ git clone https://github.com/pglombardo/PasswordPusher.git
$ cd PasswordPusher
PasswordPusher$ ls
app       bin      config     db       Gemfile.lock  log       public    README.md  TODO
app.json  Capfile  config.ru  Gemfile  LICENSE.txt   Procfile  Rakefile  script

2. デプロイ

アプリの ReadMe にも database.yml にも書いてありませんが、 Gemfile の中を確認すると production 指定でデプロイしたい場合、 PostgreSQL を使うことを想定しているようです。
なので、まず PostgreSQL のサービスを作成します。 もしデプロイする bosh-lite 環境に PostgreSQL サービスブローカがない場合、 百日行の「postgresql-cf-service-broker を Cloud Foundry で動かす 」を参考に、事前に準備をしてください。

PasswordPusher$ cf create-service PostgreSQL 'Basic PostgreSQL Plan' spwd-pg
Creating service instance spwd-pg in org horiu-jn / space horiu-jn as horiu-jn...
OK

Attention: The plan `Basic PostgreSQL Plan` of service `PostgreSQL` is not free.  The instance `spwd-pg` will incur a cost.  Contact your administrator if you think this is in error.

次に、デプロイ用のマニフェストを作成します。

PasswordPusher$ vi manifest.yml
applications:
- name: spwd-100
  command: 'RAILS_ENV=production bundle exec rake db:setup && bundle exec rackup --port $PORT'
  services:
    - spwd-pg
  • services: にバインドするサービス名を記述しておくと、 cf push した際に自動でバインドを実行してくれるため、設定しておきます。

マニフェストが作成できたら、アプリをプッシュします。

PasswordPusher$ cf push
Using manifest file /home/horiu-jn/workspace/apps/PasswordPusher/manifest.yml

Creating app spwd-100 in org horiu-jn / space horiu-jn as horiu-jn...
OK

Using route spwd-100.10.244.0.34.xip.io
Binding spwd-100.10.244.0.34.xip.io to spwd-100...
OK

Uploading spwd-100...

:

0 of 1 instances running, 1 starting
0 of 1 instances running, 1 starting
1 of 1 instances running

App started


OK

App spwd-100 was started using this command `RAILS_ENV=production bundle exec rake db:setup && bundle exec rackup --port $PORT`

Showing health and status for app spwd-100 in org horiu-jn / space horiu-jn as horiu-jn...
OK

requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: spwd-100.10.244.0.34.xip.io
last uploaded: Thu Aug 13 07:18:12 UTC 2015
stack: cflinuxfs2
buildpack: Ruby

     state     since                    cpu    memory           disk      details
#0   running   2015-08-13 04:20:53 PM   0.0%   179.7M of 256M   0 of 1G

無事成功しました。

3. 動作確認

ブラウザから、払いだされたアプリのURLへアクセスします。

Enter the Password to be Shared と表示されているフィールドへ、共有したいパスワードを入力します。
パスワードの共有リミットを期間 (Days) またはアクセス回数 (Views) を設定することも出来ます。

パスワードを入力したあと Push it! ボタンを押すと、ランダムな文字列で作成された共有用の URL が表示されます。

この URL へアクセスしてみると、先ほど登録したパスワードが表示されます。

また、設定したURLへのアクセス回数、または共有期間を超えると、パスワードは失効となります。

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



投稿者:NTTソフトウェア株式会社 堀内 純

2015-09-14

Simon Says を Cloud Foundry で動かす

「Cloud Foundry 百日行」第60日目、今日は電子ゲームの古典 Simon Says 。シンプルなゲームを簡単にデプロイして楽しめるのも、Cloud Foundry の得意分野。早速、取りかかりましょう。

基本情報

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

  • 1) ソースコードの取得
  • 2) アプリのデプロイ
  • 3) 動作確認

1. ソースコードの取得

まずはソースコードを取得し、中身を確認します。

~$ git clone https://github.com/kellyk/javascript-simon
~$ cd javascript-simon/
~/javascript-simon$ ls
css  Gruntfile.js  index.html  js  package.json  README.md  sounds

package.json があるところから、Node.js のアプリに見えますね。
しかし、ファイル構成を覗いてみると、普通の JS アプリのようにも見えます。

2. アプリのデプロイ

このアプリをどう判断するかは Cloud Foundry にお任せすることにして、まずはそのまま push しましょう。

~/javascript-simon$ cf push simon
Creating app simon in org ueno / space test1 as ueno...
OK

Creating route simon.10.244.0.34.xip.io...
OK

Binding simon.10.244.0.34.xip.io to simon...
OK

Uploading simon...
Uploading app files from: /home/ueno/javascript-simon
Uploading 205.9K, 22 files
Done uploading               
OK

Starting app simon in org ueno / space test1 as ueno...
-----> Downloaded app package (76K)
-------> Buildpack version 1.3.1
       Node.js Buildpack v64
-----> Reading application state
       package.json...
       build directory...
       cache directory...
       environment variables...
       Node engine range:   unspecified
       Npm engine:          unspecified
       Start mechanism:     none
       node_modules source: package.json
       node_modules cached: false
       NPM_CONFIG_PRODUCTION=true
       NODE_MODULES_CACHE=true
       Downloading and installing node 0.12.2...
       Using default npm version: 2.7.4
-----> Building dependencies
       Installing node modules
       npm WARN package.json simon@0.1.0 No repository field.
-----> Checking startup method
       None found
cat: /tmp/staged/app/Procfile: No such file or directory
-----> Build failed
       WARNING: Node version not specified in package.json
       WARNING: No Procfile, package.json start script, or server.js file found
-----> Finalizing build
       Creating runtime environment
       Cleaning previous cache
       Caching results for future builds
-----> Build succeeded!
       simon@0.1.0 /tmp/staged/app
       └── (empty)
       WARNING: Node version not specified in package.json
       WARNING: No Procfile, package.json start script, or server.js file found
-----> Uploading droplet (9.2M)

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 down
0 of 1 instances running, 1 failing
FAILED
Start unsuccessful

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

デプロイ失敗しました。
やはり Node.js Buildpack が選択されましたが、実は Node.js アプリでは無かったため、アプリが起動できずにいます。
デプロイ時に Buildpack の指定をせず、Node.js アプリと判定されたが、実は違っていた、ということはよくあります(百日行記事の 第25日目 等)。

package.json の中を見ても、Node や起動スクリプトの定義等はありません。
これは普通の JS アプリのようですね。

では、Staticfile Buildpack を指定して push してみましょう。

まず、Admin Buildpack の確認から。

~/javascript-simon$ cf buildpacks
Getting buildpacks...
 
buildpack              position   enabled   locked   filename   
staticfile_buildpack   1          true      false    staticfile_buildpack-cached-v1.0.0.zip   
java_buildpack         2          true      false    java-buildpack-v3.0.zip   
ruby_buildpack         3          true      false    ruby_buildpack-cached-v1.4.2.zip   
nodejs_buildpack       4          true      false    nodejs_buildpack-cached-v1.3.1.zip   
go_buildpack           5          true      false    go_buildpack-cached-v1.3.1.zip   
python_buildpack       6          true      false    python_buildpack-cached-v1.3.2.zip   
php_buildpack          7          true      false    php_buildpack-cached-v3.2.1.zip   
binary_buildpack       8          true      false    binary_buildpack-cached-v1.0.0.zip   

-b staticfile_buildpack のオプションを付けて push します。

~/javascript-simon$ cf push simon -b staticfile_buildpack
Updating app simon in org ueno / space test1 as ueno...
OK
 
Uploading simon...
Uploading app files from: /home/ueno/javascript-simon
Uploading 124.1K, 21 files
Done uploading               
OK
 
Stopping app simon in org ueno / space test1 as ueno...
OK
 
Starting app simon in org ueno / space test1 as ueno...
-----> Downloaded app package (76K)
-----> Downloaded app buildpack cache (4.0K)
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 (3.5M)
 
1 of 1 instances running
 
App started
 
 
OK
 
App simon was started using this command `sh boot.sh`
 
Showing health and status for app simon in org ueno / space test1 as ueno...
OK
 
requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: simon.10.244.0.34.xip.io
last uploaded: Thu Aug 27 00:39:55 UTC 2015
stack: cflinuxfs2
buildpack: staticfile_buildpack
 
     state     since                    cpu    memory         disk      details   
#0   running   2015-08-27 09:40:03 AM   0.0%   4.7M of 256M   0 of 1G  

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

3. 動作確認

ブラウザからアプリにアクセスします。

動作確認と言っても遊ぶだけ!
Simon Says の基本的な遊び方は以下です。

(1) Start すると、4枚のカラーパネルのうちのどこかのパネルが一回光るのでそこをクリック
(2) 次にまたその同じパネルが光り、続いてまたどこか別のパネルが光るので、その二つを順番にクリック
(3) 次に、1回目、2回目のパネルがまた順番に光り、続いてまたどこか別のパネルが光るので、その三つを順番にクリック
 :
(N) 1回目、2回目… N 回目のパネルが順番に光るので、その N 個を順番にクリック
 :

記憶が持つ限り、光るパネルは一つずつ増えていきます。
どこまで記憶が持つか挑戦しましょう。

まとめ

手軽にデプロイして、手軽に使う、いや、遊ぶ。今日は Cloud Foundry ならではの手軽さを感じられるアプリでした。

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

2015-09-11

Ghost を Cloud Foundry で動かす

「Cloud Foundry 百日行」第59日目は,Node.js ベースのブログ・プラットフォーム Ghost です。Markdown で記事が書けて,リアルタイムでプレビューもできるあたりが魅力的です。

基本情報

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

  • 1) ソースコードの取得
  • 2) Cloud Foundry 向け変更
  • 3) サービスの作成とバインド
  • 4) アプリの起動
  • 5) 初期設定&動作確認

1. ソースコードの取得

今回は 公式サイトのインストール手順 に従って,最新版を公式サイトからダウンロードします。検証時点での最新版は 0.7.0 でした。

$ curl -L https://ghost.org/zip/ghost-latest.zip -o ghost.zip
$ mkdir ghost
$ cd ghost/
$ unzip ../ghost.zip

以下は必須ではありませんが,後の修正のために,Gitで管理します。

$ git init
$ git add .
# git commit -m "Unzipped"

2. Cloud Foundry 向け変更

Deploy Ghost blog to Cloud Foundry を参考に,cfenv パッケージを package.json に追加します。

$ emacs package.json
..
$ git diff -- package.json
diff --git a/package.json b/package.json
index acf20d5..94619dc 100644
--- a/package.json
+++ b/package.json
@@ -67,7 +67,8 @@
   },
   "optionalDependencies": {
     "mysql": "2.1.1",
-    "pg": "4.1.1"
+    "pg": "4.1.1",
+    "cfenv": "1.0.0"
   },
   "devDependencies": {
     "bower": "1.4.1",

参考記事では cf-env パッケージを使うことになっていますが,cf-env は廃されて cfenv になったので,この記事ではそちらを使いました。

cf. https://www.npmjs.com/package/cf-env

次に,config.example.js をもとに config.js を作成&変更します。変更箇所は以下の通りです。

$ cp config.example.js config.js
$ emacs config.js
..
$ git diff --no-index -- config.example.js config.js
diff --git a/config.example.js b/config.js
index d6813db..197274f 100644
--- a/config.example.js
+++ b/config.js
@@ -6,24 +6,29 @@
 var path = require('path'),
     config;

+var cfenv = require('cfenv');
+var appEnv = cfenv.getAppEnv();
+
 config = {
     // ### Production
     // When running Ghost in the wild, use the production environment.
     // Configure your URL and mail settings here
     production: {
-        url: 'http://my-ghost-blog.com',
+        url: (appEnv.url.replace(/https/, 'http') || 'http://cf-ghost.10.244.0.34.xip.io'),
         mail: {},
         database: {
-            client: 'sqlite3',
-            connection: {
-                filename: path.join(__dirname, '/content/data/ghost.db')
+            client: 'mysql',
+            connection: appEnv.getServiceCreds(/^mysql.*/).uri,
+            pool: {
+                min: 2,
+                max: 4
             },
             debug: false
         },

         server: {
-            host: '127.0.0.1',
-            port: '2368'
+            host: (appEnv.bind || '0.0.0.0'),
+            port: (appEnv.port || process.env.PORT)
         }
     },

この変更は, Deploy Ghost blog to Cloud Foundrycfenv パッケージのドキュメント を参考に行いました。cfenvを使って,アプリのURLの設定,サービスの設定 (名前が mysql で始まるサービスがあれば自動的に設定されます),待ち受けるホスト及びポートの設定を行っています。

さらに,Deploy Ghost blog to Cloud Foundry を参考に Procfile を追加します。

$ echo 'web: NODE_ENV=production npm start' > Procfile
$ cat Procfile
web: NODE_ENV=production npm start

最後に,npm-shrinkwrap.json を削除します。削除の理由は,npm-shrinkwrap.json があると,そちらが優先されて package.json の変更が反映されないためです。本来は npm shrinkwrap して npm-shrinkwrap.json を作り直すのが筋ですが,その場合 node や npm がない環境ではそれらのインストールが必要になります。それを避けてデプロイ手順を単純にするために,本記事では削除を選択しました。削除しても Cloud Foundry 側で package.json に基づいて npm install が行われるので,バージョン間の差異で大きな影響が出なければ問題ありません。

$ git rm npm-shrinkwrap.json
rm 'npm-shrinkwrap.json'

以上で Cloud Foundry 向けの変更は終わりです。

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

アプリを停止状態でプッシュし,サービスを作成してバインドします。

3.1. アプリの作成

サービスとバインドするために,アプリを停止状態で Cloud Foundry 環境にプッシュします。

$ cf push cf-ghost --no-start

3.2. サービスの作成

Ghost では RDBMS として SQLite, MySQL, PostgreSQL の3つが使えますが, 公式ドキュメント には

Support for Postgres is currently second class compared to SQLite & MySQL - There is a build run against it, but very minimal manual testing.

とあるので,ここでは MySQL を使います。

$ cf create-service p-mysql 100mb mysql-ghost

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

$ cf bind-service cf-ghost mysql-ghost

4. アプリの起動

準備ができたので,アプリを起動します。 cf start または cf push で起動できます。

$ cf push cf-ghost
Updating app cf-ghost in org nota-ja / space 100 as nota-ja...
OK
..
requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: cf-ghost.10.244.0.34.xip.io
last uploaded: Thu Sep 10 10:13:45 UTC 2015
stack: cflinuxfs2
buildpack: Node.js

     state     since                    cpu    memory           disk      details
#0   running   2015-09-10 07:15:31 PM   0.0%   183.9M of 256M   0 of 1G

起動しました。

5. 動作確認

アプリのURLにブラウザーからアクセスすると最初に表示される画面は↓です:

公式ドキュメント に基づいて /ghost/setup/ にアクセスすると,アカウント作成画面になります:

次の画面に進んでアカウント情報を入力します:

【Invite your team】の画面は,とりあえず画面下部にある【I’ll do it later, take me to my blog!】のリンクをクリックしてスキップします:

すると管理画面のトップに移動するので,右上の【NEW POST】をクリックして,

新規投稿画面に入り,記事を書き込んでみます:

Markdown で入力した記事(左側)が即座にプレビュー(右側)に反映されるので,非常に編集しやすく感じました。

記事を公開するには,右上の【SAVE DRAFT】の右の下向き矢印をクリックすると表示される【Publish Now】をクリックし,

さらにそのあと赤く表示される【PUBLISH NOW】を再度クリックします:

公開された記事を見るには,左下の【VIEW BLOG】をクリックします。

すると別タブが開いて,そこにブログのトップ画面が表示されるので,

今書いた記事へのリンクをクリックすると,

記事が表示されます:

使い勝手はほんとうに良い感じで,可能ならばこのブログも移行したいくらいです。

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

2015-09-10

Orion を Cloud Foundry で動かす

本日の「Cloud Foundry百日行」第58日目は Orion エディター です。

Orion エディターは、IBM Canadaの Ottawa研究所で開発されているオープンソースの
エディターです。有名な Eclipse IDEの発祥地です。

普段 Orion Editor を使って開発しているのですが、ファイルシステムが必要なため
Cloud Foundry のような PaaS では、あまり使えないのではないかなと思っていました。しかし、
ふと以下の目的に限定すれば使えるのではないか?と思い直し、百日行に公開しようと踏み切りました。

  • JavaScriptファイルを整形したい
  • Cloud Foundry のコンテナに端末アクセスしたい

JavaScript ファイルは以前開発したものを、再利用することが多いですが、コピー&ペースト
するとインデントの位置がくるってしまうことがしばしばあります。JS Beautify (http://jsbeautifier.org/) で整形したりするのですが、 エディターを離れるし、そもそもオンライン版だと多少心配です。Orion のプラグインとして入れておけばエディターを離れることなく整形できます。

またCloud Foundry 百日行26回でも紹介した tty.js の代わりにもなります(参照: tty.js を Cloud Foundry で動かす ) 。実際には、tty.js が Orion エディターに組み込まれています。

今回紹介するのは、Node.js版のOrion軽量版です。

基本情報

 

デプロイ

1. package.json の準備

Orion Node.js 版は Nodeパッケージ管理(npm)に組み込まれているので、package.json ファイルだけ あれば動作します。以下のファイルを適切なディレクトリに用意します。

$ cat package.json
{
   "name": "orion",
  "version": "0.0.0",
  "description": "",
   "main": "server.js",
   "dependencies": {
    "orion": "~0.0.37"
    }
}

基本的には “dependencies” に orion パッケージを記述するだけです。それでは Cloud Foundry に デプロイしてみましょう。

2. Cloud Foundry にデプロイ

npm でパッケージを入れると node_modules/ にはいるので、起動コマンドオプションで
orion パッケージを指定します。

$ cf push orion -n amntorion -c 'node node_modules/orion/server.js -port $PORT --workspace /home' -m 256M
requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: amntorion.eu-gb.mybluemix.net
last uploaded: Thu Sep 10 02:19:07 UTC 2015
stack: lucid64

     state     since                    cpu    memory          disk          details
#0   running   2015-09-10 11:19:56 AM   0.0%   42.3M of 256M   86.9M of 1G

Cloud Foundry としては今回は Bluemix を利用しました。指定した url にアクセスすると Orion Editor が開きます。




3.JS Beautifyプラグインの追加

Orion エディターには様々なプラグインが公開されており、機能を追加できるようになっています。ここでは、JS Beautify のプラグインを入れてみます。

左側の "Setting" から Plugins を選びます。 右上に "Get Plug-ins" ボタンがあるのでクリックします。


Orion エディターで利用できるプラグイン一覧がでますので、JS Beautify を選択して、"Submit" ボタンで導入します。



それでは、動作確認をしてみましょう。


動作確認

1. 動作確認 (JS Beautify)

File->New->File メニューで適当な JavaScript ファイルを作成します(例では script.js)。エディターが開くので、かなり適当な JavaScript を記述します。



Tools-> Format JS メニューを選択します。



JavaScript ファイルが整形されました。





2. 動作確認 (端末)

左側にある “Console” を開くと、ターミナルモードになります。Node.js ビルドパックを使っているので、node コマンドが使えました。



 

おまけ

Orionは Markdown エディターでもあるので、このブログエントリーの初校も Orion Editor で書いています。簡単な .md 文書を書くにはお手軽だと思います。ただ Node.js 版だと Chrom ブラウザで日本語処理に少し難がありました。あまり国際化を意識していなさそうです。

Orion Editor には Java版があり、こちらの方が高機能です。実は Java 版は Cloud Foundry
へのデプロイができる機能が備わっています。なにかの機会があれば Java版もぜひお試しください。

なお今回利用した環境はだれでもアクセスできるので、削除しました。あしからず。公開された Cloud Foundry で動かす場合には、--random-route などのオプションをつけることをお勧めします。

今回使用した環境


2015-09-09

slackinを Cloud Foundry で動かす

「Cloud Foundry 百日行」第57日目は、slackin です。

最近はSlackを利用する事が多くなってきており、業務で利用するだけでなく、ちょっとした集まり場のコミュニケーション手段としても Slackのチームを作ってやりとりされる事が多くなってきました。

そうした中で誰でも参加可能なSlackのチームを作成するには、 通常の場合、既に登録しているメンバーが個別に招待を送る等の作業が必要となります。

Node-REDの百日業記事を見てから個人的にすっかりハマってしまい「Slackのチームがあれば便利かも?」と思っていたタイミングで Node.js繋がりでElectronも興味があったのでElectronの日本のユーザ向けSlackチャンネルに参加した所、登録フォームがslackinが使われていて存在を知りました。

そこで今回はslackinをCloud Foundry上でデプロイする方法について紹介していきたいと思います。

基本情報

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

  • 1) ソースコードの取得
  • 2) 事前準備
  • 3) アプリの起動
  • 4) 動作確認

1. ソースコードの取得

$ https://github.com/rauchg/slackin
$ cd slackin/
$ ls
Dockerfile  History.md  Makefile  Procfile  Readme.md  app.json  bin  lib  package.json  test

2. 事前準備

2.1. 招待用のSlack Token作成

まず招待可能にしたいSlackチームにログインした状態で以下のURLにアクセスします。

Token発行用URL

URLを開いたページの"Authentication"にチームが表示されているので 招待したいチームのUser横にある"Create token"をクリックしトークンを作成しメモします。

トークン例:

xoff-10101000505-10520015205-51021255215-505005

トークンのメモが完了したら準備完了です。

3. アプリの起動

slackinの設定はアプリケーションpushの際に-cの引数として渡していきます。

-cでslackin(実行ファイル名)の後にチームのサブドメインとトークンの順番に設定します。 ※アプリケーション名は設定するslackチームのサブドメインと同じにすると分かりやすいです。

cf push SLACK_SUB_DOMAIN -m 128m -c 'slackin SLACK_SUB_DOMAIN SLACK_TOKEN'

push時のコマンド例: node-red-jp.slack.comの場合は以下の様に記述

cf push node-red-jp -m 128m -c 'slackin node-red-jp xoff-10101000505-10520015205-51021255215-505005'
:
App started


OK

App node-red-jp was started using this command `slackin node-red-jp xoff-10101000505-10520015205-51021255215-505005`

Showing health and status for app node-red-jp in org hogehoge@hotmail.co.jp / space dev as hogehoge@hotmail.co.jp...
OK

requested state: started
instances: 1/1
usage: 128M x 1 instances
urls: node-red-jp.mybluemix.net
package uploaded: Tue Sep 8 13:18:49 UTC 2015

     state     since                    cpu    memory        disk          details
     #0   running   2015-09-08 10:22:11 PM   0.0%   57M of 128M   67.9M of 1G

成功しました。

4. 動作確認

ブラウザからアプリにアクセスします。

"you@yourdomain.com"にSlackに招待したい自分のメールアドレスを入力し "GET MY INVITE"をクリックすると登録完了となり設定したメールアドレスに招待メールが到着します。

まとめ

今回は非常に軽量でシンプルなアプリでしたが、実用性の高いアプリケーションで こういった普段使いの便利ツールもCloud Foundry上でデプロイする事で 開発スピードを加速することが出来るのがPaaSの魅力だと思っています。

またSlackの登録を自動化する試みは 色々な方がチャレンジしているようで少し調べただけでも以下の物があり、 そのうちの幾つかはherokuを意識した作りになっているので 興味をもたれ方は是非他のものもチャレンジして頂ければと思います。

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