We removed our free Sandbox April 25th.
You can read more on our blog.

Node.js

Note

CLI Command examples on this page are always provided without the --application (shorthand -A) argument, assuming you’re running these commands in a connected folder (at creation or using the dotcloud connect command). For more details on connected folders, see Migrating to the CLI 0.9.

The nodejs service can host any Node.js application. The application can be a HTTP server or just a background worker: the deployment method will be the same. Background workers will be allocated to a HTTP virtual host as well, but it won’t be used, and so nothing bad will happen.

Note

For the impatient...

  • create a three-lines supervisord.conf file;
  • if you need to install external dependencies, use a standard NPM package.json file (but this step is optional);
  • if your app should be reachable through HTTP, make sure your code is setup to listen on port 8080 (don’t worry, it will be exposed on port 80 anyway, but you need to listen on port 8080 in your app).

Basic Use

Let’s assume that you are building a dotCloud application called “ramen”. For the sake of simplicity, we will also assume that everything related to this application is located in a directory called “ramen-on-dotcloud”.

Let’s setup our environment:

mkdir ramen-on-dotcloud
cd ramen-on-dotcloud
dotcloud create ramen

A dotCloud application is described by a Build File (dotcloud.yml), which is a simple YAML file named “dotcloud.yml” located in our “ramen-on-dotcloud” directory. To add a new service to our app, we just add the following lines to “ramen-on-dotcloud/dotcloud.yml”:

www:
  type: nodejs
  approot: hellonode

This Build File tells the dotCloud platform that the code for your Node.js app will be under “hellonode”. Our code will have the following structure:

ramen-on-dotcloud/
|_ dotcloud.yml         (dotCloud Build File shown above)
|_ hellonode/           (your application root or "approot")
   |_ supervisord.conf  (mandatory boilerplate file; see next paragraph)
   |_ package.json      (optional file to specify NPM dependencies)
   |_ server.js         (your app; can be named differently)
   |_ ...               (other files: code, static assets...)

Note

Your main Node.js program does not have to be called server.js, but it is “good practice”.

Assuming that you want to run the code inside the file named “server.js” located at the root of your application, you need to create the following “ramen-on-dotcloud/hellonode/supervisord.conf” file:

[program:node]
command = node server.js
directory = /home/dotcloud/current

Note

When you will push your code to dotCloud, it will be groomed by the builder process, and your approot will be mapped to /home/dotcloud/current. That’s why you need to specify this path.

You can configure many options in the [program:x] section (like environment variables). See the Supervisor reference for more information.

Note

We called the Supervisor configuration section “program:node”, but “program:anything” will do as well. Just in case you were wondering.

We don’t need to specify any extra dependency for our small “Hello, World!” app. That will be covered later, in nodejs-packagejson.

Let’s write a simple Node.js app now. It will answer to every request with “Hello World!” as well as the list of the HTTP headers found in the request. Paste the following code into “ramen-on-dotcloud/hellonode/server.js”:

require('http').createServer(function (request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  output = "Hello World!\n";
  for (k in request.headers) {
    output += k + '=' + request.headers[k] + '\n';
  }
  response.end(output);
}).listen(8080);

Note

The “node” process will run on port 8080 for security reasons (port 80 requires root), but don’t worry: you will be able to access it through http://something.dotcloud.com/ without specifying the port number.

We can now push our application to dotCloud:

dotcloud push

URLs will be generated for each web service in our application. Open your browser to see your new service in action!

If you want to attach a better URL to your application, read the Custom Domains documentation.

Node.js Versions

The node.js service supports three different branches of Node.js (v0.4.x, v0.6.x, v0.8.x), it will default to node.js v0.4.x unless you specify otherwise. The current versions of each node.js branch are listed in the table below. Pick the branch that works best for you.

branch version variable
v0.4.x* v0.4.12 v0.4.x
v0.6.x v0.6.20 v0.6.x
v0.8.x v0.8.3 v0.8.x

* Node.js v0.4.x is the default

To configure your service to use a version of Node.js other than v0.4.x, you will set the node_version config option in your dotcloud.yml

For example, this is what you would have if you wanted to use Node.js version v0.6.x:

www:
  type: nodejs
  approot: hellonode
  config:
    node_version: v0.6.x

Warning

The config dictionary of a service is applied when your service is launched for the first time. If you change it, you will need to destroy the concerned service and push your application again to apply the changes.

WebSockets

A lot of people use Node.js for real-time web applications, and want to leverage on WebSockets for that purpose. WebSockets is fully supported on dotCloud. See our WebSockets guide for more information.

Node.js Workers

Sometimes, you need to run a program for a longer time than a single HTTP request. Use cases include:

  • CPU-intensive jobs (e.g. video transcoding);
  • running some code at a specified time, or on regular intervals;
  • background activity (e.g. crawling 3rd party service to update your database);
  • run a specific web server, like Node.js or Tornado;
  • and much more!

dotCloud provides “worker services” dedicated to those tasks. There is a different service for each language: Ruby Worker, PHP & PHP Worker, Perl Worker, Python worker, Node.js... The only difference between them is the set of pre-installed packages, and dependencies handling: python-worker supports requirements.txt, while —for instance— ruby-worker supports Gemfile.

All worker services rely on Supervisor to start and monitor your processes. Supervisor will start defined programs automatically, and will restart them automatically if they crash or exit. If you just need to run a program at a specified interval, you can also use a crontab and ignore Supervisor.

Note

You can also use a “non-worker” service to run some background jobs. More specifically, all services feature crontab, allowing you to run Periodic Tasks. So if you want to run a daily Python script, e.g., a stock ticker in your database, you don’t have to dedicate a python-worker to this task: you cansetup the crontab in the same python service that you use for your web application. However, you should be aware that when you scale your application, the cron tasks will be scheduled in all scaled instances – which is probably not what you need! So in many cases, it will still be better to use a separate service.

Similarly, a lot of (non-worker) services already run Supervisor, so you can run additional background jobs in those services. Then again, remember that those background jobs will run in multiple instances if you scale your application. Moreover, if you add background jobs to your web service, it will get fewer resources to serve pages, and your performance will take a significant hit.

Technically, if you really want to know – there is almost no difference between worker and non-worker services. For instance, the python-worker service is basically the python service without Nginx (HTTP server) and uWSGI (Python web workers) running. Both can optionally run background processes using Supervisor.

NPM Dependencies (with package.json)

If your application already ships a package.json file, it will be automatically used: just after your code is deployed, “npm install” will be run from your code directory.

If you want to specify your dependencies that way, you can adapt the following package.json file:

{
  "name": "helloworld",
  "version": "1.0.0",
  "dependencies": {
    "express": "2.0.0",
    "underscore": ""
  }
}

See the NPM documentation to see the full range of options available in package.json.

Listen on Port 8080

Your main program (it should be “server.js”, right?) must listen on port 8080. If this confuses you: don’t worry, it is usually very easy to fix. Just look for the ”.listen(XXXX);” part in your code and replace XXXX with 8080.

Note

Of course, you can ignore this part if your Node.js program does not need to listen for HTTP requests. That might be the case if it will only do background processing, crawling, etc.

Troubleshooting

You can check if your daemon has been started properly with the following command:

dotcloud run www supervisorctl status

If everything’s fine, you should see an output similar to this one:

node                           RUNNING    pid 975, uptime 0:03:20

Supervisor will capture the output (stdout and stderr) of your programs, and write it into log files. You can check those logs with the dotcloud logs command:

dotcloud logs www

Note

Anything printed to stderr is written right away in the log file. However, stdout will be buffered. That means that messages might not show up immediately. With Node you can use the “util” module to write on stderr: “require(‘util’).debug”.

Press Ctrl+C to stop watching the logs.

Signal Handlers

If your application needs to do some housekeeping when it exits (which will happen each time you push a new version of the code, since the old version will be stopped, and the new one will be started), you can setup a signal handler.

Just include a snippet similar to the following one:

process.on('SIGTERM', function () {
    console.log('Got SIGTERM exiting...');
    // do some cleanup here
    process.exit(0);
});

Note

The “Got SIGTERM exiting...” message will never show up in the logs, because Supervisor stops capturing output as soon as you issue supervisorctl stop. But don’t worry, the callback is correctly executed.

Thanks to Daniel Gasienica for his awesome feedback and ideas.