Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using PM2, how can I deploy my node.js app to multiple environments and ports on the same server?

I have an ecosystem.json file for my node app that I deploy using PM2.

I've tried configuring it a bunch of different ways, but have not had luck accomplishing my goal which is to:

  • be able to deploy to either production or staging environment (currently both on same server).
  • When deploying to one, the other should stay running as well.
  • The 2 different environments should be on different ports (prod = 8000, staging = 3000)

What happens is whichever deploy command I run first wins.

So if I do pm2 deploy production and then pm2 deploy staging, only the production app/port combo is running on the server, and vice versa if I switch the order.

EDIT: If I use the conf below, there will be 2 apps running in pm2 status, but if I do a netstat, I only see the first one's port. (centos 6)

I feel like I must be missing something obvious. Here's my ecosystem.json file, I have tried it with and without multiple app declarations at the top.

{
  /**
   * Here we declare the apps that must be managed by PM2
   * All options are listed here:
   * https://github.com/Unitech/PM2/blob/master/ADVANCED_README.md#json-app-declaration
   *
   */
  apps : [
    {
      "name"       : "myapp-staging",
      "script"     : "app.js",
      "instances"  : "1",
      "error_file" : "/var/log/nodejs/myapp.mydomain.com-staging-err.log",
      "out_file"   : "/var/log/nodejs/myapp.mydomain.com-staging-out.log",
      "pid_file"   : "/home/node/myapp.mydomain.com-staging.pid",
      "exec_mode"  : "cluster_mode",
      "env_staging" : {
        "NODE_ENV": "staging", "PORT": 3000
      },
      "env_production" : {
        "NODE_ENV": "production", "PORT": 8000
      }
    },
    {
      "name"       : "myapp-production",
      "script"     : "app.js",
      "instances"  : "1",
      "error_file" : "/var/log/nodejs/myapp.mydomain.com-staging-err.log",
      "out_file"   : "/var/log/nodejs/myapp.mydomain.com-staging-out.log",
      "pid_file"   : "/home/node/myapp.mydomain.com-staging.pid",
      "exec_mode"  : "cluster_mode",
      "env_production" : {
        "NODE_ENV": "production", "PORT": 8000
      }
    }

  ],


  /**
   * PM2 help you to deploy apps over your servers
   * For more help go to :
   * https://github.com/Unitech/PM2/blob/master/ADVANCED_README.md#deployment-pm2--090
   */
  deploy : {
    production : {
      user : "node",
      host : "node01.mydomain.com",
      ref  : "origin/master",
      repo : "[email protected]:mydomain/mydomain-myapp.git",
      path : "/var/production/myapp.mydomain.com-production/",
      "post-deploy" : "npm prune && npm install -l && pm2 startOrGracefulReload ecosystem.json --env production",
      env  : {
        NODE_ENV: "production",
        PORT: 8000
      }
    },
    staging : {
      user : "node",
      host : "node01.mydomain.com",
      ref  : "origin/master",
      repo : "[email protected]:mydomain/mydomain-myapp.git",
      path : "/var/production/myapp.mydomain.com-staging/",
      "post-deploy" : "npm prune && npm install -l && pm2 startOrGracefulReload ecosystem.json --env staging",
      env  : {
        NODE_ENV: "staging",
        PORT: 3000
      }
    }
  }
}
like image 937
k00k Avatar asked Apr 28 '15 15:04

k00k


2 Answers

You can use a shell environment variable and then use javascript inside the pm2 configuration file. For example if your configuration file has ...

    "apps": [
    {
        "script": "app/server.js",
        "PORT" : process.env.NODE_ENV == "development" ? 8888 : 9999,
        "name": "MemsharpWeb-" + process.env.NODE_ENV,

And you run pm2 from the command line like this

   NODE_ENV=production pm2 start config.json

the port number will be set to 9999.

like image 152
Bryan Avatar answered Sep 20 '22 12:09

Bryan


Answering my own question here. Though not a perfect solution, the way I've accomplished this (for now) is by using 2 separate ecosystem.json files, one for each environment. I have ecosystem.json setup for staging and ecosystem-prod.json setup for production.

So now to deploy to staging I do a standard: pm2 deploy staging and for production I do a slightly more wordy: pm2 deploy ecosystem-prod.json production

Obviously not ideal, but until someone tells me otherwise, might be the only way to do it on the same box with different ports.

like image 34
k00k Avatar answered Sep 21 '22 12:09

k00k