Friday, October 9, 2015
How to deploy a Hello World node.js app from your laptop to IBM BlueMix
Introduction
I recently had the opportunity to begin learning IBM BlueMix.
To get started, I wanted to deploy a trivial Hello World program written in javascript/node.js. And I wanted to do as many tasks as possible from the command line instead of the BlueMix web interface, because the web interface is useless for scripting and automation.
It wasn't easy. I couldn't find complete and simple docs that worked. Many docs I found were out-of-date, or focused on selling services. It took me two days, working sporadically, to figure this out. Thankfully, I found answers from bloggers (links included below).
Caveats
The steps below worked on my Linux laptop (Ubuntu 12.04). Mac should be similar.
I obfuscated my real email address to myname@example.com for privacy in the listings below.
Prereqs
Required: Get yourself an account at IBM Bluemix. https://console.ng.bluemix.net/
Required: Install the Cloud Foundy command line interface tool, cf, on your laptop. Fetch it from https://github.com/cloudfoundry/cli/releases (as of this writing, I installed CF version v6.12.4, Linux 32-bit binary.) Un-tar it and add it to your path. IBM Doc: https://www.ng.bluemix.net/docs/starters/install_cli.html
Recommended: Install node.js on your laptop and add it to your path. https://nodejs.org/en/ Reason: It can be used to test the hello world locally on your laptop.
Part 1. Prepare node.js app on your laptop
First create a node.js app and package.json file in the same folder on your laptop...
Create a new folder on your laptop for the app.
Create a file in that folder named hellohttp.js. I found a trivial HTTP server app written by Tim Caswell. Browse here and search for 'Hello HTTP': http://howtonode.org/hello-node Paste the contents into the file and save it.
Important: To support port mapping within BlueMix, edit the app to use environment variable VCAP_APP_PORT as shown below. This code will listen on port 8000 on your laptop (where the env var is NOT defined), or on the BlueMix-defined port when deployed to BlueMix (where the env var IS defined)
// Source: Hello HTTP by Tim Caswell http://howtonode.org/hello-node
// Load the http module to create an http server.
var http = require('http');
// Configure our HTTP server to respond with Hello World to all requests.
var server = http.createServer(function (request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.end("Hello World\n");
});
// Listen on port VCAP_APP_PORT (if defined) or 8000 (default).
var port = process.env.VCAP_APP_PORT || 8000;
server.listen(port);
// Put a friendly message on the terminal
console.log("Server running at http://127.0.0.1:" + port + "/");
Next create a file named package.json in the same folder as the hello http app. Copy/paste the following content into the file. Edit your personal info.
Note: The most important statement in this file is the scripts.start definition. BlueMix issues this command to start your app.
I found this solution in a blog post by Brian Innes. Brian documented several ways to start apps in BlueMix. https://www.ibm.com/developerworks/community/blogs/enablingwithbluemix/entry/confused_about_how_to_specify_a_start_command_for_node_js_application_on_ibm_bluemix?lang=en
Of course, as soon as I discovered Brian's solution, I also found the package.json technique in the official docs: https://www.ng.bluemix.net/docs/#starters/nodejs/index.html#nodejs Ugh.
{
"name": "hellohttp",
"version": "0.0.1",
"description": "hellohttp",
"author": "myname@example.com",
"contributors": [
{ "name": "myname",
"email": "myname@example.com" }
],
"scripts": {
"start": "node hellohttp.js"
}
}
Local test
If you installed node.js on your laptop, test the hellohttp.js app by running it locally.
Start
node hellohttp.js
See response
Server running at http://127.0.0.1:8000/
Verify
netstat -na | grep LIST | grep 8000
tcp 0 0 0.0.0.0:8000 0.0.0.0:* LISTEN
Verify again
Browse to http://localhost:8000, see response 'Hello World'.
Part 2. Upload node.js app to BlueMix
From the same folder, issue these Cloud Foundry cf commands...
Set the API
cf api https://api.ng.bluemix.net
Get response
Setting api endpoint to https://api.ng.bluemix.net...
OK
API endpoint: https://api.ng.bluemix.net (API version: 2.27.0)
Not logged in. Use 'cf login' to log in.
Log in
cf login -u myname@example.com -o myname@example.com -s dev
where -o is org, -u is username (both are the same when you first start using BlueMix), and -s is space dev.
and enter your password when prompted
Password> ********
Get response
Authenticating...
OK
Targeted org myname@example.comn
Targeted space dev
API endpoint: https://api.ng.bluemix.net (API version: 2.27.0)
User: myname@example.com
Org: myname@example.com
Space: dev
Deploy the app. The command 'cf push' will upload all files in your folder to BlueMix (recursively).
cf push hellohttp
Wait a few minutes to receive this entire response...
Creating app hellohttp in org myname@example.com / space dev as myname@example.com...
OK
Creating route hellohttp.mybluemix.net...
OK
Binding hellohttp.mybluemix.net to hellohttp...
OK
Uploading hellohttp...
Uploading app files from: /home/myname/sandbox/nodejs/hellohttp
Uploading 1.1K, 2 files
Done uploading
OK
Starting app hellohttp in org myname@example.com / space dev as myname@example.com...
-----> Downloaded app package (4.0K)
-----> IBM SDK for Node.js Buildpack v2.5-20150902-1526
Based on Cloud Foundry Node.js Buildpack v1.5.0
-----> Creating runtime environment
NPM_CONFIG_LOGLEVEL=error
NPM_CONFIG_PRODUCTION=true
NODE_MODULES_CACHE=true
-----> Installing binaries
engines.node (package.json): unspecified
engines.npm (package.json): unspecified (use default)
Resolving node version (latest stable) via 'node-version-resolver'
Installing IBM SDK for Node.js (0.12.7) from cache
Using default npm version: 2.11.3
-----> Restoring cache
Loading 1 from cacheDirectories (default):
- node_modules (not cached - skipping)
-----> Checking and configuring service extensions before installing dependencies
-----> Building dependencies
Pruning any extraneous modules
Installing node modules (package.json)
-----> Checking and configuring service extensions after installing dependencies
-----> Installing App Management
-----> Caching build
Clearing previous node cache
Saving 1 cacheDirectories (default):
- node_modules (nothing to cache)
-----> Build succeeded!
└── (empty)
-----> Uploading droplet (14M)
0 of 1 instances running, 1 starting
1 of 1 instances running
App started
OK
App hellohttp was started using this command `./vendor/initial_startup.rb`
Showing health and status for app hellohttp in org myname@example.com / space dev as myname@example.com...
OK
requested state: started
instances: 1/1
usage: 1G x 1 instances
urls: hellohttp.mybluemix.net
last uploaded: Wed Oct 7 15:11:49 UTC 2015
stack: cflinuxfs2
buildpack: SDK for Node.js(TM) (ibm-node.js-0.12.7)
state since cpu memory disk details
#0 running 2015-10-07 11:12:56 AM 0.0% 55.2M of 1G 48.2M of 1G
Verify
Determine the URL for your app. Browse to the BlueMix web interface, look for your new app, and see the URL (in blue):
Browse to the URL and see 'Hello World'. For example, mine was:
http://hellohttp.mybluemix.net/
Done
It worked. Claim success.
Labels:
bluemix,
deploy,
hello world,
ibm,
javascript,
node,
node.js
Subscribe to:
Posts (Atom)