Skip to main content

Deploying a Node.js/socket.io app to Openshift

4 min read

Older Article

This article was published 12 years ago. Some information may be outdated or no longer applicable.

Following on from my previous article on how to deploy a Node.js & MongoDB app to AppFog, here’s how to deploy your app to Openshift.

I like AppFog, but there’s something missing from their offerings: socket.io and websocket support. As I kept building my chat application, I needed somewhere to deploy it for further testing, and websocket support was non-negotiable.

Openshift gives you 3 “gears” (instances) for free. They’re sized “small,” meaning you get the basic setup (512 MB compared to AppFog’s 2GB, plus 1GB of disk space). In more technical terms:

A Gear is a container with a set of resources that allows users to run their applications. OpenShift runs many Gears on each virtual machine and dynamically distributes Gears across them.

Here’s what you need to get up and running with Openshift. I’m assuming you’ve already registered. My preference is the command line, but you can use their web interface to achieve the same thing.

First, install rhc (Openshift’s CLI). On a Unix system, run:

sudo gem install rhc

Once installed, set up your environment. The rhc tool has a built-in command for this:

rhc setup

I set up an authorisation token with my server, which means I can connect to my Openshift instances without re-entering credentials.

With that done, create an application:

rhc app create nodesocketapp nodejs-0.10

(To see what cartridges are available, run rhc cartridge list.)

Now the tricky part. Deploying to Openshift is Git-based. Every time you push a change to your local Git repo, the changes get pushed to Openshift. It shuts down your app, copies the changes over, runs scripts like npm install, and starts the application back up.

If you want to deploy an app that’s already under Git control, I’d recommend creating an Openshift branch. Here’s how.

First, grab the Git URL that was generated when you created the application:

rhc app show nodesocketapp | grep Git

(rhc app show [appname] displays all the info about your app.)

Navigate to your application folder on your local machine and add Openshift as a remote:

git remote add openshift -f [git URL copied before]

Then merge your local code with the code on Openshift:

git merge openshift/master -s recursive -X ours

After the merge, push your changes:

git push openshift HEAD

From this point on, every time you make a local change, just run git push openshift to update the live app.

Once I deployed, I hit a few issues. First, bower install failed. I tried two approaches:

  • SSH into my instance by running rhc ssh [appname]. Because of the authorisation key we set up earlier, this works automatically (you’ll need to accept the RSA fingerprint the first time). Your app lives under app-root/repo. If you try to install bower packages there, you’ll likely get a “bash: bower: command not found” error.
  • The second option: navigate into the right node_modules folder while still SSH’d in, and run bower from there:
cd node_modules/bower/bin
./bower install

But this throws an EACCESS “permission denied” error for /var/lib/openshift/[instance-id]/.local. You don’t have write access to the home folder.

The fix is simple. As part of npm install, you can add variables and run commands from your package.json. Add the following section (or extend your existing scripts section):

"scripts": {
    "postinstall": "export HOME=/var/lib/openshift/[instance-id]/app-root/runtime/repo; ./node_modules/bower/bin/bower install"
  },

This sets a new HOME directory (one that’s writable) and automatically runs bower install.

I’d also recommend locking down your dependency versions by creating an npm-shrinkwrap.json file. Install the shrinkwrap npm package and run npm shrinkwrap.

Finally, some code changes are probably needed to make websockets work.

Make sure you’re using the right ports. Add the following lines to your Node.js/Express.js configuration (output trimmed):

var express = require('express'),
  app = express(),
  server = require('http').createServer(app),
  io = require('socket.io').listen(server);
//... more config and code
app.set('port', process.env.OPENSHIFT_NODEJS_PORT || 3000);
app.set('ipaddr', process.env.OPENSHIFT_NODEJS_IP || '127.0.0.1');
//... code to continue

And here’s the crucial bit: regardless of what port you used during testing, when you deploy to Openshift you need the ports above. From the client side, connect on port 8000:

var socket = io.connect('http://your-app-url.rhcloud.com:8000');

That’s it. If everything’s wired up correctly, your Node.js/socket.io app should be running on Openshift.

I’ve updated my chat app on GitHub to be “Openshift ready,” so feel free to check it out and experiment. (Note: some things still need changing, e.g. the websocket in the repo tries to connect to localhost on port 3000.)

I found a few bugs in my code that need fixing (mostly triggered when accessing the page from a mobile browser), so I’ll be busy updating the repo.

Good luck with the deployment.