AMS Node Meetup December presentation Phusion Passenger

Preview:

Citation preview

Deploying with

Phusion Passenger

Our Node.js app is done. How do we deploy to production?

Can’t be that hard. Let’s ask Google.

Make sure your app keeps running(restart on crash)

Step 1

forever  start  app.js

Start your app on system boot

Step 2

systemd, SysV init,upstart, etc.

#!/bin/bash  DIR=/var/www/YOUR_NODE_APP_GOES_HERE  PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin  NODE_PATH=/usr/local/lib/node_modules  NODE=/usr/local/bin/node      test  -­‐x  $NODE  ||  exit  0      function  start_app  {      NODE_ENV=production  nohup  "$NODE"  "$DIR/YOUR_APP_SERVER_FILE.js"  1>>  "$DIR/logs/YOUR_APP_NAME.log"  2>&1  &      echo  $!  >  "$DIR/pids/YOUR_APP.pid"  }      function  stop_app  {      kill  `cat  $DIR/pids/YOUR_APP.pid`  }      case  $1  in        start)              start_app  ;;          stop)              stop_app  ;;          restart)              stop_app              start_app              ;;          *)              echo  "usage:  YOUR_APP_NAME  {start|stop}"  ;;  esac  exit  0

Reverse proxy from Nginx!

Step 3

• Serve files faster and better• Improves security: better

HTTP sanitizer!• Easier SSL configuration

server  {          listen  0.0.0.0:80;          server_name  yourdomain.com  yourdomain;          root  /yourapp/public;  }

server  {          listen  0.0.0.0:80;          server_name  yourdomain.com  yourdomain;          root  /yourapp/public;  

       location  ~*  \.(css|js|gif|jpe?g|png)$  {                  add_header  Pragma  public;                  add_header  Cache-­‐Control  "public,  must-­‐revalidate,  proxy-­‐revalidate";          }  }

upstream  app_yourdomain  {          server  127.0.0.1:3000;  }  

server  {          listen  0.0.0.0:80;          server_name  yourdomain.com  yourdomain;          root  /yourapp/public;  

       location  ~*  \.(css|js|gif|jpe?g|png)$  {                  add_header  Pragma  public;                  add_header  Cache-­‐Control  "public,  must-­‐revalidate,  proxy-­‐revalidate";          }  

       location  /  {              proxy_set_header  X-­‐Real-­‐IP  $remote_addr;              proxy_set_header  X-­‐Forwarded-­‐For  $proxy_add_x_forwarded_for;              proxy_set_header  Host  $http_host;              proxy_set_header  X-­‐NginX-­‐Proxy  true;  

           proxy_pass  http://app_yourdomain/;              proxy_redirect  off;          }  }

Multi-core!

Step 4

Cluster module

var  cluster  =  require('cluster');  var  http  =  require('http');  var  numCPUs  =  require('os').cpus().length;  

if  (cluster.isMaster)  {      //  Fork  workers.      for  (var  i  =  0;  i  <  numCPUs;  i++)  {          cluster.fork();      }  

   cluster.on('exit',  function(worker,  code,  signal)  {          console.log('worker  '  +  worker.process.pid  +  '  died');      });  }  else  {      //  Workers  can  share  any  TCP  connection      //  In  this  case  its  a  HTTP  server      http.createServer(function(req,  res)  {          res.writeHead(200);          res.end("hello  world\n");      }).listen(8000);  }

How can we see application statistics? Uhhh.... sign up with

proprietary monitoring services?

Configure forever

Configure init

Configure Nginx

Use Cluster module

Sign up for proprietary monitoring service

Node.js≠

boilerplate

Passenger: rethinking the workflow

server  {          listen  0.0.0.0:80;          server_name  yourdomain.com;          root  /yourapp/public;  }

server  {          listen  0.0.0.0:80;          server_name  yourdomain.com;          root  /yourapp/public;          deploy_my_damn_app  on;  }

server  {          listen  0.0.0.0:80;          server_name  yourdomain.com;          root  /yourapp/public;          deploy_my_damn_app  on;  }

✓ Restarting on crash✓ Start during system

boot✓ Nginx reverse proxy✓ Multi-core

server  {          listen  0.0.0.0:80;          server_name  yourdomain.com;          root  /yourapp/public;          deploy_my_damn_app  on;  }

✓ Restarting on crash✓ Start during system

boot✓ Nginx reverse proxy✓ Multi-core

bash$  show-­‐my-­‐app-­‐status

server  {          listen  0.0.0.0:80;          server_name  yourdomain.com;          root  /yourapp/public;          deploy_my_damn_app  on;  

}

✓ Restarting on crash✓ Start during system

boot✓ Nginx reverse proxy✓ Multi-core

bash$  show-­‐my-­‐app-­‐status

       passenger_enabled  on;

bash$  passenger-­‐status

#  passenger-­‐status  -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐  General  information  -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐  Max  pool  size  :  9  Processes          :  3  Requests  in  top-­‐level  queue  :  0  

-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐  Application  groups  -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐  /u/apps/bubbleconf/current#default:      App  root:  /u/apps/bubbleconf/current      Requests  in  queue:  0      *  PID:  25408      Sessions:  0              Processed:  4              Uptime:  4h  17m  2s          CPU:  0%            Memory    :  95M          Last  used:  34m  30s  a  

/u/apps/passenger_website/current#default:      App  root:  /u/apps/passenger_website/current      Requests  in  queue:  0      *  PID:  20696      Sessions:  0              Processed:  27291      Uptime:  6h  10m  0s          CPU:  8%            Memory    :  155M        Last  used:  0s  ago

#  passenger-­‐config  system-­‐metrics  -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐  General  -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐  Kernel  version        :  3.14.1-­‐x86_64-­‐linode39  Uptime                        :  225d  15h  52m  20s  Load  averages          :  0.10%,  0.10%,  0.13%  Fork  rate                  :  0  

-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐  CPU  -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐  Number  of  CPUs        :        4  Average  CPU  usage  :    14%    -­‐-­‐    10%  user,      0%  nice,      4%  system,    86%  idle      CPU  1                      :      0%    -­‐-­‐      0%  user,      0%  nice,      0%  system,  100%  idle      CPU  2                      :    40%    -­‐-­‐    40%  user,      0%  nice,      0%  system,    60%  idle  I/O  pressure            :      0%      CPU  1                      :      0%      CPU  2                      :      0%  Interference  from  other  VMs:      0%      CPU  1                                        :      0%      CPU  2                                        :      0%  

-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐  Memory  -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐  RAM  total                  :      6008  MB  RAM  used                    :      1940  MB  (32%)  RAM  free                    :      4068  MB  Swap  total                :      1711  MB  Swap  used                  :        172  MB  (10%)  Swap  free                  :      1539  MB

Nginx

Forever/PM2

Cluster

Init script

Monitoring software

Lets you focus on what is

really important

Keeps you

out of the dark

Identify and solve

problems

How it works

Easy to migrate to? Easy to setup?

$  brew  install  passenger  $  brew  install  nginx  —with-­‐passenger  …follow  instructions…

OS X

…add  our  APT  repo…  $  sudo  apt-­‐get  install  passenger  nginx-­‐extras

Debian/Ubuntu

$  node  app.js  

$  passenger  start  \      —app-­‐type  node  —startup-­‐file  app.js

Standalone mode

Nginx mode

server  {          listen  0.0.0.0:80;          server_name  yourdomain.com;          root  /yourapp/public;          passenger_enabled  on;  }

Is it any good?

Is it stable?

Who uses it?

6 years

• Host multiple apps at once• Improve security with privilege separation• Dynamic worker management• etc…

Many more features not mentioned

• Zero-downtime rolling restarts• Error resistant deploys• Mass deployment• Resource control• Unstuck stuck apps• Memory limiting• Priority support

Paid offering

The future

Easily setup dev environmentwith one command

• Repeatable• Shareable

Easily setup and push to productionwith one command

• Repeatable• Shareable

Debugging

www.phusionpassenger.com

Recommended