IBM Bluemix から提供されている Node.js ランタイムを使ってみました。Bluemix 上で Node.js を使う場合特有のクセとかコツとかも含めて、その時の様子をまとめてみました:
2015100701


なお、今回は Bluemix 上へのデプロイを cf ツールで行います。cf ツールがインストール済みであることが前提になるので、導入できていない場合はお使いの環境にあった cf ツールをダウンロードして、インストールしておいてください:
https://github.com/cloudfoundry/cli/releases


まず、(Bluemix でない)一般的な Node.js 環境でハローワールド的なアプリを書くと、そのコードはこんな感じになると思います:
var http = require( 'http' );
var server = http.createServer(); // HTTPサーバー

// リクエストを受けたらメッセージを返すだけの処理
server.on( 'request', function( req, res ){
  res.write( 'ハロー Node.js ワールド!' );
  res.end();
});

server.listen( 80 ); // 80 番ポートで起動する場合

仮にこの内容を server.js というファイルで用意したのであれば、以下のコマンドで HTTP サーバーを起動して待ち受けることができます:
# node server.js


そして、このサーバーに対してブラウザで(普通に80番ポートに)アクセスすると、こんな感じで、期待通りのメッセージが表示されます:
2015100702


これと同じことを Bluemix で実現するにはどうすればいいでしょうか?まずは違いが分かるようにちょっとだけ server.js のメッセージを変えておきます:
var http = require( 'http' );
var server = http.createServer(); // HTTPサーバー

// リクエストを受けたらメッセージを返すだけの処理
server.on( 'request', function( req, res ){
  res.write( 'ハロー Node.js ワールド on Bluemix!' );
  res.end();
});

server.listen( 80 ); // 80 番ポートで起動する場合

次に Bluemix 上に Node.js のランタイムを作成しておきます。この例では dotnsf-js という名称で Node.js ランタイムを作っています。今回はサービスは不要です:
2015100703


そして普通の Bluemix 感覚で、この server.js だけが存在しているディレクトリを用意した状態で cf ツールからプッシュして、、、

いやいやいや、これでは動くはずがありません。プッシュした後に
# node server.js
のコマンドを実行する必要があるのに、その指定をしていません。


Bluemix では、これらランタイムの挙動に関する指定は package.json というファイルを作って指定する必要があります。今回は起動時に "node server.js" を実行する、というコマンドを指定したいので、以下のような内容の package.json ファイルを(server.js と同じフォルダに)作成します:
{
  "scripts": {
    "start": "node server.js"
  }
}

この server.js と package.json の2つのファイルが存在している状態で、そのフォルダから cf コマンドで Node.js ランタイムにプッシュしてみます:
> cf push dotnsf-js(ここは作成した Node.js ランタイムの名称)
Updating app dotnsf-js in org dotnsf@jp.ibm.com / space dev as dotnsf@jp.ibm.com...
OK

Uploading dotnsf-js...
   :
   :(結構時間がかかります)
   :
0 of 1 instances running, 1 failing
FAILED
Start unsuccessful

TIP: use 'cf logs dotnsf-js --recent' for more information

>

なんとプッシュが失敗してしまいました。何が原因なのでしょう?

メッセージにあるように "cf logs dotnsf-js --recent' コマンドで最新ログを見てみるとこんな感じのログが出力されていました:
> cf logs dotnsf-js --recent
   :
   :
   :
2015-10-07T11:49:36.80+0900 [App/0]      OUT > node server.js
2015-10-07T11:49:36.96+0900 [App/0]      ERR events.js:85
2015-10-07T11:49:36.96+0900 [App/0]      ERR       throw er; // Unhandled 'error' event
2015-10-07T11:49:36.96+0900 [App/0]      ERR             ^
2015-10-07T11:49:36.96+0900 [App/0]      ERR Error: listen EACCES
2015-10-07T11:49:36.96+0900 [App/0]      ERR     at exports._errnoException (util.js:746:11)
2015-10-07T11:49:36.96+0900 [App/0]      ERR     at Server._listen2 (net.js:1139:19)
2015-10-07T11:49:36.96+0900 [App/0]      ERR     at listen (net.js:1182:10)
2015-10-07T11:49:36.96+0900 [App/0]      ERR     at Server.listen (net.js:1267:5)
2015-10-07T11:49:36.96+0900 [App/0]      ERR     at Object. (/home/vcap/app/server.js:13:8)
2015-10-07T11:49:36.96+0900 [App/0]      ERR     at Module._compile (module.js:460:26)
2015-10-07T11:49:36.96+0900 [App/0]      ERR     at Object.Module._extensions..js (module.js:478:10)
2015-10-07T11:49:36.96+0900 [App/0]      ERR     at Module.load (module.js:355:32)
2015-10-07T11:49:36.96+0900 [App/0]      ERR     at Function.Module._load (module.js:310:12)
2015-10-07T11:49:36.96+0900 [App/0]      ERR     at Function.Module.runMain (module.js:501:10)
   :
   :
   :

"node server.js" を実行した後に Server.listen が失敗しているっぽい。それってソースでいうと最後の
   :
   :
   :
server.listen( 80 ); // 80 番ポートで起動する場合

の部分ってこと? あれ、80 番ポートじゃないんだっけ?


実は Bluemix (CloudFoundry)上の Node.js は 80 番では起動しません。特定のあるポート番号で起動させて、それを 80 番ポートから転送しているのです(つまり直接 80 番ポートで起動させることが間違い)。

では何番のポートを指定して起動すればいいのでしょうか? この答は「環境変数から取得する必要がある」のでした。

というわけで、server.js を以下のように書き換えます:
var http = require( 'http' );
var server = http.createServer();

var cfenv = require( 'cfenv' );
var appEnv = cfenv.getAppEnv();

server.on( 'request', function( req, res ){
  res.write( 'ハロー Node.js ワールド on Bluemix!' );
  res.end();
});

server.listen( appEnv.port );

"cfenv" というモジュールを使って、CloudFoundry としてのランタイムの環境情報を取り出しています。そして listen の引数として指定するポート番号を、この環境情報のポート番号を参照して指定するように書き換えました。

また、cfenv モジュールを動的にロードするため、package.json ファイルにも変更を加えます。このアプリケーションの dependencies に cfenv を加えます:
{
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "cfenv": "1.0.x"
  }
}

cfenv は 1.0.* というバージョンを使いたいのですが、↑このように指定しておくと、1.0.x の最新版を探して加えてくれます:


これで準備が整いました。改めてこの2つのファイル(server.js と package.json)がカレントフォルダにある状態で cf ツールでプッシュすると成功して、Bluemix 上のランタイムにアクセスできるようになります:
2015100704



この「必要なモジュールを package.json の dependencies に指定してロードして使う」というのは、Node.js の便利なモジュール(Express とか ejs とか)を Bluemix 上で使う場合に必要になるので、覚えておくといいと思いました。