Saturday, April 23, 2011

Hello, Cloud Foundry running node.js

Contrary to most people's view on the Amazon cloud outage incident, I believe this actually shows the power and outreach of the cloud computing. The technology needs some time to mature and become reliable, let's just be patient. It is very exciting to see even big sites like reddit, quora was affected, and even the cloud service provider Heroku was one of the victims.

There are many new players in the cloud computing field and Cloud Foundry from VMWare is definitely a very disruptive force to the current market. Currently, it supports Spring for Java apps, Rails and Sinatra for Ruby apps, JVM frameworks like Grails and Node.js! Best of all, the whole platform is open sourced.

CF provides a Micro Cloud for individual developers, for free now ;-) This is how to get a helloworld node.js app running:


1. Preparation

- Sign up for the free Micro Cloud for Cloud Foundry (http://www.cloudfoundry.com/).
- Wait a few days (mine took 9 days) and you will receive an approval email.
- Cloud Foundry uses a CLI tool called vmc for interactions with your Micro Cloud instance. Follow the instructions and use the credentials in the approval email to set up vmc (see "vmc getting started guide", really wish it is available not only in PDF format).

2. Write a helloworld node.js app

As of this writing, CF supports node.js-0.4.5 (use "vmc runtimes" to find out). The only thing that is different in the CF environment is that the system will assign a host and port to your application. CF adds several environment variables accessible through process.env.

For our helloworld, we are interested in VCAP_APP_HOST and VCAP_APP_PORT (there are also VMC_APP_HOST and VMC_APP_PORT, which seems still exist but will be deprecated).

So, you basically create a directory (I use the same appid as the directory name) and create an app.js for hello world like this:
var http = require('http'),
    port = Number(process.env.VCAP_APP_PORT || 3000),
    host = process.env.VCAP_APP_HOST || 'localhost';

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Welcome to Cloud Foundry!\n' +
            host + ':' + port + '\n' +
            require('util').inspect(process.env, false, null));
}).listen(port, host);

console.log('Server running at http://' + host + ':' + port + '/');
This simple app just prints out "Welcome to Cloud Foundry!" and a bunch of environment variables ;-) Note that we put localhost and 3000 there so that it is easier to debug the app on a local node.js installation.

3. Deploy using vmc

The very first time you deploy the app, you run "vmc push <appid>". Note that you need to pick an id that is not being used, otherwise, you will get an error. It would be really nice for CF to provide a Web UI to check what appid is still available. You just follow the instructions and see the output. If everything goes well, you will see your app running at http://<appid>.cloudfoundry.com/.

To update your app, you need to run "vmc update <appid>" instead of "vmc push <appid>". You can also delete your app using "vmc delete <appid>".

vmc CLI provides many operations, "vmc -h" is your best friend to find and try them out.

4. Add npm module dependencies

In most cases, you will need to use dependent NPM modules such as Connect, Express, etc. With the current node.js 0.4.5 supported on CF, it is very straightforward.

- You create a package.json that defines your app/module with dependencies.
- Then you run "npm bundle", which creates a node_modules directory with all the required NPM modules.
- Finally, you do "vmc update <appid>" and you are done.

Here is a quick sample:

package.json
{
    "name": "helloworld-node",
    "version": "0.0.1",
    "dependencies":
        {
            "connect": "*"
        }
}

app.js
var connect = require('connect');

connect.createServer(function(req, res) {
    var body = 'hello, cloud foundry';
    res.setHeader('Content-Length', body.length);
    res.end(body);
}).listen(process.env.VCAP_APP_PORT || 3000);

console.log('connect server listening...');

dir structure: 
app.js, package.json, node_modules

5. To learn more

I will try to update this helloworld guide and add a bit about bundling dependent npm modules. To learn more about Cloud Foundry, read the CF blog and code, since it is open sourced, you can simply install it from github.

Updated: found a recent post about using MongoDB on cloudfoundry ;-)