9. Bluemix is IBM's Platform-as-a-
Service Offering.
It's built on top of Cloud Foundry.
It also uses Docker and OpenStack
(but we're not covering those today)
9
10. With Bluemix, you write
applications and deploy ("push")
them to the server.
Bluemix manages the details
– Provisioning VMs
– Setting up the Containers
– Routing,
– Load-Balancing,
– Scaling,
– Configuring Services, etc
10
15. "Buildpack" – a collection of scripts
that prepare code for execution in
Bluemix.
…tells Bluemix how to set up the
VM, Container and Runtime for
your application to run.
For Node.js applications deployed
to Bluemix, the default Buildpack is
"sdk-for-nodejs"
15
17. You will interact with Bluemix using
both the browser-based UI and the
Cloud Foundry cf command line
client.
17
Visit:
https://github.com/cloudfoundry/cli/releases
Once installed, cf will be added to your PATH. You may need
to restart your terminal session to pick up the change.
$ cf -version
19. Once the cf command line tool is
installed, you have to tell it about
the Bluemix endpoint.
19
First, what region are you in?
US South (`us-south`):
https://api.ng.bluemix.net
Europe United Kingdom (`eu-gb`):
https://api.eu-gb.bluemix.net ✔
20. Once the cf command line tool is
installed, you have to tell it about
the Bluemix endpoint.
20
Second, set the API endpoint and Login
$ cf api https://api.eu-gb.bluemix.net
$ cf login
Enter your Bluemix User ID and Password to authenticate
22. 22
$ mkdir helloworld && cd helloworld && npm init
…
name: (helloworld)
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
…
Is this ok? (yes)
Remember what you choose here
23. 23
$ vi index.js
var http = require('http');
var server = http.createServer(function(req,res) {
res.writeHead(200,
{'Content-Type': 'text/plain'});
res.end('Hello World');
});
server.listen(8888, function() {
console.log('The server is running');
});
27. 27
$ vi index.js
var http = require('http');
var server = http.createServer(function(req,res) {
res.writeHead(200,
{'Content-Type': 'text/plain'});
res.end('Hello World');
});
server.listen(
process.env.VCAP_APP_PORT || 8888,
function() {
console.log('The server is running');
}
);
28. 28
$ vi manifest.yml
---
applications:
- name: {yourappname}
mem: 128M
instances: 1
path: .
host: {yourappname}
Pick something unique for
the application name
http://{yourappname}.mybluemix.net
29. 29
$ vi .cfignore
node_modules
$ ls –a
.cfignore
index.js
package.json
manifest.yml
This tells cf not to upload your
local node_modules, Bluemix will
install them for you.
34. Services are additional managed
capabilities that can be added to an
application.
34
$ cf marketplace
$ cf marketplace –s rediscloud
$ cf create-service rediscloud 30mb myrediscloud
Creates an instance of the rediscloud
service within your account.
35. Services are additional managed
capabilities that can be added to an
application.
35
$ cf bind-service {yourappname} rediscloud
$ npm install --save redis
Attach the myrediscloud service instance to your application
Add the redis client module to your application.
36. 36
$ vi index.js
var http = require('http');
var redis = require('redis');
var vcap_services = process.env.VCAP_SERVICES;
var rediscloud_service =
JSON.parse(vcap_services)["rediscloud"][0];
var credentials =
rediscloud_service.credentials;
var client = redis.createClient(
credentials.port,
credentials.hostname,
{no_ready_check: true});
client.auth(credentials.password);
client.on('connect', function() {
console.log('Connected to Redis');
});
var server = http.createServer(function(req,res) {
client.get('last-visit', function(err, reply) {
res.writeHead(200, {'Content-Type': 'text/plain'});
client.set('last-visit', new Date().toISOString());
res.write('Last Visit: ' + reply + 'n');
res.end('Hello World');
});
});
server.listen(process.env.VCAP_APP_PORT || 8888, function() {
console.log('The server is running');
});
37. 37
$ vi index.js
var http = require('http');
var redis = require('redis');
var vcap_services = process.env.VCAP_SERVICES;
var rediscloud_service =
JSON.parse(vcap_services)["rediscloud"][0];
var credentials =
rediscloud_service.credentials;
var client = redis.createClient(
credentials.port,
credentials.hostname,
{no_ready_check: true});
client.auth(credentials.password);
client.on('connect', function() {
console.log('Connected to Redis');
});
var server = http.createServer(function(req,res) {
client.get('last-visit', function(err, reply) {
res.writeHead(200, {'Content-Type': 'text/plain'});
client.set('last-visit', new Date().toISOString());
res.write('Last Visit: ' + reply + 'n');
res.end('Hello World');
});
});
server.listen(process.env.VCAP_APP_PORT || 8888, function() {
console.log('The server is running');
});
38. 38
$ vi index.js
var http = require('http');
var redis = require('redis');
var vcap_services = process.env.VCAP_SERVICES;
var rediscloud_service =
JSON.parse(vcap_services)["rediscloud"][0];
var credentials =
rediscloud_service.credentials;
var client = redis.createClient(
credentials.port,
credentials.hostname,
{no_ready_check: true});
client.auth(credentials.password);
client.on('connect', function() {
console.log('Connected to Redis');
});
var server = http.createServer(function(req,res) {
client.get('last-visit', function(err, reply) {
res.writeHead(200, {'Content-Type': 'text/plain'});
client.set('last-visit', new Date().toISOString());
res.write('Last Visit: ' + reply + 'n');
res.end('Hello World');
});
});
server.listen(process.env.VCAP_APP_PORT || 8888, function() {
console.log('The server is running');
});
39. 39
$ vi index.js
var http = require('http');
var redis = require('redis');
var vcap_services = process.env.VCAP_SERVICES;
var rediscloud_service =
JSON.parse(vcap_services)["rediscloud"][0];
var credentials =
rediscloud_service.credentials;
var client = redis.createClient(
credentials.port,
credentials.hostname,
{no_ready_check: true});
client.auth(credentials.password);
client.on('connect', function() {
console.log('Connected to Redis');
});
var server = http.createServer(function(req,res) {
client.get('last-visit', function(err, reply) {
res.writeHead(200, {'Content-Type': 'text/plain'});
client.set('last-visit', new Date().toISOString());
res.write('Last Visit: ' + reply + 'n');
res.end('Hello World');
});
});
server.listen(process.env.VCAP_APP_PORT || 8888, function() {
console.log('The server is running');
});
40. 40
$ vi index.js
var http = require('http');
var redis = require('redis');
var vcap_services = process.env.VCAP_SERVICES;
var rediscloud_service =
JSON.parse(vcap_services)["rediscloud"][0];
var credentials =
rediscloud_service.credentials;
var client = redis.createClient(
credentials.port,
credentials.hostname,
{no_ready_check: true});
client.auth(credentials.password);
client.on('connect', function() {
console.log('Connected to Redis');
});
var server = http.createServer(function(req,res) {
client.get('last-visit', function(err, reply) {
res.writeHead(200, {'Content-Type': 'text/plain'});
client.set('last-visit', new Date().toISOString());
res.write('Last Visit: ' + reply + 'n');
res.end('Hello World');
});
});
server.listen(process.env.VCAP_APP_PORT || 8888, function() {
console.log('The server is running');
});
43. Bluemix uses environment
variables to configure your
application
43
VCAP_APP_PORT - The TCP Port
VCAP_APP_HOST - The Hostname
VCAP_SERVICES - *JSON* File with
Service Details
VCAP_APPLICATION - *JSON* file with
Application details
48. The Application Management Tools
are additional utilities for debugging
and managing applications
48
$ cf set-env {yourappname} BLUEMIX_APP_MGMT_ENABLE
proxy+devconsole+shell+inspector+trace
$ cf restage {yourappname}
Enables:
• a terminal shell for command line
access to your application's container
• a node-inspector instance
• debug tracing using log4js, bunyan, etc
52. You can enable tracing using log4js
or bunyan
52
$ npm install --save log4js@0.6.22
$ vi index.js
...
var log4js = require('log4js');
log4js.loadAppender('console');
var logger = log4js.getLogger('app');
logger.setLevel('ERROR');
...
logger.info('running...');
...
53. Set the trace level from within the Bluemix
Dashboard…
53
55. Use cf logs to view the trace output
55
$ cf logs {yourappname}
$ cf logs --recent {yourappname}
Tails the logs to the console
Prints the most recent logs
57. The default Node.js Buildpack uses
Node.js v0.12.7, which is good.
But I want to use the new stuff.
57
The IBM Node.js Buildpack is based on the open source
Cloud Foundry Node.js Buildpack. Nearly all Cloud Foundry
Buildpacks can work on Bluemix out of the box.
58. 58
The Heroku Node.js Buildpack:
https://github.com/heroku/heroku-buildpack-nodejs.git
Includes support for the latest Node.js/io.js Binaries
59. You specify the alternate buildpack in the
manifest.yml
59
$ vi manifest.yml
---
applications:
- name: {yourappname}
mem: 128M
instances: 1
path: .
host: {yourappname}
buildpack: https://github.com/heroku/heroku-buildpack-
nodejs.git
command: node app
60. And tell package.json which version of
the Node runtime to use
60
$ vi package.json
{
"name": "helloworld",
"version": "1.0.0",
"main": "./app.js",
"scripts": {
"start": "node app"
},
...,
"engines": {
"iojs" : "*"
}
}
63. Bluemix supports User-Provided
Services.
63
User Provided Services are essentially service configurations
you provide. They are kept separate from your application so
that they can be shared and managed just like the services
provided by Bluemix itself.
User Provided Services provide an excellent way of providing
runtime configuration setting to your applications.
64. For instance, suppose we need to
configure a secret for our
applications:
64
$ cf cups session-secret -p secret
secret> this is the secret
Creating user provided service session-secret in org jasnell / space
dev as jasnell...
$ cf bind-service {yourappname} session-secret
$ cf restage
67. Bluemix supports Custom Domain
Names
67
By default, Bluemix will create a URL for your application
automatically.
This usually follows the pattern:
http://{yourappname}.mybluemix.net
But what if you want to use your own domain name?
68. A few command line calls is all you
need.
68
$ cf create-domain myorg example.org
$ cf map-route {yourappname} example.org --n foo
Then create a CNAME DNS record for your sub-domain:
foo.example.org CNAME {yourappname.mybluemix.net}
Once the DNS records propagate, your application will be available at:
http://foo.example.org
69. You can upload your SSL/TLS
certificates via the dashboard:
69
71. Updating an application on Bluemix
will cause the application to restart,
forcing a small downtime period.
You can avoid it.
71
$ cf rename {yourappname} {youappname}-old
$ cf push
$ cf delete {yourappname}-old