nodejs-app

Deploy a Node.js application - supports PM2, systemd, Docker, or Kubernetes

Recipaie - Deployment Recipe

The template that describes how to deploy this service.

Raw JSON
{
  "$schema": "https://recipaie.com/schemas/recipaie.schema.json",
  "name": "nodejs-app",
  "version": "1.0.0",
  "description": "Deploy a Node.js application - supports PM2, systemd, Docker, or Kubernetes",
  "prerequisites": [
    "Node.js 18+ runtime (unless using containerized deployment)",
    "Application source code or container image",
    "One of: PM2 process manager, systemd, Docker, or Kubernetes"
  ],
  "steps": [
    {
      "order": 1,
      "what": "Assess deployment environment",
      "why": "Node.js apps can run in many ways - choose what fits your infrastructure",
      "when": "Before deployment",
      "how": "Evaluate options: (1) PM2 - simple process manager with clustering and monitoring, (2) systemd - native Linux service management, (3) Docker - containerized isolation, (4) Kubernetes - orchestrated containers. Consider: existing infrastructure, scaling needs, monitoring requirements",
      "verify": "Deployment method chosen based on infrastructure assessment",
      "comments": [
        "PM2 is simplest for single-server deployments",
        "systemd integrates with Linux service management",
        "Docker/K8s best for consistent environments and horizontal scaling"
      ]
    },
    {
      "order": 2,
      "what": "Install Node.js runtime",
      "why": "Required for PM2 and systemd deployments (containers include runtime)",
      "when": "If using PM2 or systemd deployment",
      "skip_if": "Using Docker/K8s (runtime included in image), or Node.js already at required version",
      "how": "Install via package manager: (Ubuntu) curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt install nodejs, (RHEL) dnf module install nodejs:20, (macOS) brew install node@20, (nvm) nvm install 20",
      "verify": "node --version shows v20.x or higher",
      "comments": [
        "Use LTS versions for production (20.x, 22.x)",
        "nvm allows multiple Node versions on same machine",
        "Consider using mise or asdf for polyglot version management"
      ]
    },
    {
      "order": 3,
      "what": "Prepare application",
      "why": "Application needs dependencies and build artifacts",
      "when": "Before running the application",
      "skip_if": "Using pre-built container image with all dependencies",
      "how": "Clone repo or copy source, then: npm ci --production (or npm install --production). If TypeScript or build step required: npm run build",
      "verify": "node_modules exists, build artifacts present if applicable",
      "comments": [
        "npm ci is faster and more reliable than npm install for CI/CD",
        "Use --production to skip devDependencies",
        "For containers: multi-stage build to keep image small"
      ]
    },
    {
      "order": 4,
      "what": "Configure environment variables",
      "why": "12-factor app configuration via environment",
      "when": "Before starting the application",
      "how": "Set required environment variables: NODE_ENV=production, PORT=3000, plus app-specific config. Method depends on deployment: (PM2) ecosystem.config.js env section, (systemd) Environment= in unit file, (Docker) -e flags or env_file, (K8s) ConfigMap/Secret",
      "verify": "Environment variables accessible to application process",
      "comments": [
        "Never commit secrets to source control",
        "Use secret management for sensitive values (Vault, AWS Secrets Manager, K8s Secrets)",
        "Consider .env files for local development only"
      ]
    },
    {
      "order": 5,
      "what": "Deploy and start application",
      "why": "Run the application with your chosen method",
      "when": "After application is prepared",
      "how": "Start using chosen method: (PM2) pm2 start ecosystem.config.js && pm2 save, (systemd) systemctl start myapp && systemctl enable myapp, (Docker) docker run -d --name myapp -p 3000:3000 myapp:latest, (K8s) kubectl apply -f deployment.yaml",
      "verify": "curl http://localhost:3000/health returns success response",
      "comments": [
        "PM2: use pm2 startup to configure boot persistence",
        "systemd: create /etc/systemd/system/myapp.service unit file",
        "Always implement a health check endpoint"
      ]
    },
    {
      "order": 6,
      "what": "Configure process management and monitoring",
      "why": "Ensure application restarts on crash and is monitored",
      "when": "After initial deployment succeeds",
      "skip_if": "Orchestrator handles this (K8s has built-in restart policies)",
      "how": "Configure restart policies: (PM2) automatic with configurable max restarts, (systemd) Restart=always in unit file, (Docker) --restart=unless-stopped. Set up monitoring: PM2 has built-in metrics, or use external APM (Datadog, New Relic, etc.)",
      "verify": "Kill the app process - it should automatically restart within seconds",
      "comments": [
        "PM2: pm2 monit for real-time monitoring",
        "Consider log aggregation (publog, ELK, CloudWatch)",
        "Set up alerting for downtime and error rates"
      ]
    }
  ],
  "step_count": 6
}
Version: 1.0.0
Steps: 6

Prerequisite

Steps

1 Assess deployment environment
Why
Node.js apps can run in many ways - choose what fits your infrastructure
When
Before deployment
How
Evaluate options: (1) PM2 - simple process manager with clustering and monitoring, (2) systemd - native Linux service management, (3) Docker - containerized isolation, (4) Kubernetes - orchestrated containers. Consider: existing infrastructure, scaling needs, monitoring requirements
Verify
Deployment method chosen based on infrastructure assessment
Comments
  • PM2 is simplest for single-server deployments
  • systemd integrates with Linux service management
  • Docker/K8s best for consistent environments and horizontal scaling
2 Install Node.js runtime
Why
Required for PM2 and systemd deployments (containers include runtime)
When
If using PM2 or systemd deployment
Skip If
Using Docker/K8s (runtime included in image), or Node.js already at required version
How
Install via package manager: (Ubuntu) curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt install nodejs, (RHEL) dnf module install nodejs:20, (macOS) brew install node@20, (nvm) nvm install 20
Verify
node --version shows v20.x or higher
Comments
  • Use LTS versions for production (20.x, 22.x)
  • nvm allows multiple Node versions on same machine
  • Consider using mise or asdf for polyglot version management
3 Prepare application
Why
Application needs dependencies and build artifacts
When
Before running the application
Skip If
Using pre-built container image with all dependencies
How
Clone repo or copy source, then: npm ci --production (or npm install --production). If TypeScript or build step required: npm run build
Verify
node_modules exists, build artifacts present if applicable
Comments
  • npm ci is faster and more reliable than npm install for CI/CD
  • Use --production to skip devDependencies
  • For containers: multi-stage build to keep image small
4 Configure environment variables
Why
12-factor app configuration via environment
When
Before starting the application
How
Set required environment variables: NODE_ENV=production, PORT=3000, plus app-specific config. Method depends on deployment: (PM2) ecosystem.config.js env section, (systemd) Environment= in unit file, (Docker) -e flags or env_file, (K8s) ConfigMap/Secret
Verify
Environment variables accessible to application process
Comments
  • Never commit secrets to source control
  • Use secret management for sensitive values (Vault, AWS Secrets Manager, K8s Secrets)
  • Consider .env files for local development only
5 Deploy and start application
Why
Run the application with your chosen method
When
After application is prepared
How
Start using chosen method: (PM2) pm2 start ecosystem.config.js && pm2 save, (systemd) systemctl start myapp && systemctl enable myapp, (Docker) docker run -d --name myapp -p 3000:3000 myapp:latest, (K8s) kubectl apply -f deployment.yaml
Verify
curl http://localhost:3000/health returns success response
Comments
  • PM2: use pm2 startup to configure boot persistence
  • systemd: create /etc/systemd/system/myapp.service unit file
  • Always implement a health check endpoint
6 Configure process management and monitoring
Why
Ensure application restarts on crash and is monitored
When
After initial deployment succeeds
Skip If
Orchestrator handles this (K8s has built-in restart policies)
How
Configure restart policies: (PM2) automatic with configurable max restarts, (systemd) Restart=always in unit file, (Docker) --restart=unless-stopped. Set up monitoring: PM2 has built-in metrics, or use external APM (Datadog, New Relic, etc.)
Verify
Kill the app process - it should automatically restart within seconds
Comments
  • PM2: pm2 monit for real-time monitoring
  • Consider log aggregation (publog, ELK, CloudWatch)
  • Set up alerting for downtime and error rates

Prodaie - Execution Record

What happened when an AI executed this recipe in different environments.

Key difference: Each step adds

success

(bool) and

details

(string) fields to record what actually happened.

Raw JSON
{
  "$schema": "https://recipaie.com/schemas/prodaie.schema.json",
  "name": "nodejs-app",
  "description": "Deployment record showing Node.js app deployed via different methods: PM2, Docker, and Kubernetes",
  "prerequisites": [
    "Node.js 18+ runtime (unless using containerized deployment)",
    "Application source code or container image",
    "One of: PM2 process manager, systemd, Docker, or Kubernetes"
  ],
  "locations": [
    {
      "path": "dev-server (PM2)",
      "description": "Single development server using PM2 for process management",
      "status": "complete",
      "step_count": 6,
      "steps": [
        {
          "order": 1,
          "what": "Assess deployment environment",
          "why": "Node.js apps can run in many ways - choose what fits your infrastructure",
          "when": "Before deployment",
          "how": "Evaluate options: PM2, systemd, Docker, or Kubernetes",
          "verify": "Deployment method chosen based on infrastructure assessment",
          "success": true,
          "details": "chose PM2 for simplicity, already familiar with ecosystem.config.js"
        },
        {
          "order": 2,
          "what": "Install Node.js runtime",
          "why": "Required for PM2 and systemd deployments",
          "when": "If using PM2 or systemd deployment",
          "skip_if": "Using Docker/K8s or Node.js already at required version",
          "how": "Install via package manager or nvm",
          "verify": "node --version shows v20.x or higher",
          "success": true,
          "details": "nvm install 20 && nvm use 20, shows v20.10.0"
        },
        {
          "order": 3,
          "what": "Prepare application",
          "why": "Application needs dependencies and build artifacts",
          "when": "Before running the application",
          "skip_if": "Using pre-built container image",
          "how": "npm ci --production, then npm run build if needed",
          "verify": "node_modules exists, build artifacts present",
          "success": true,
          "details": "npm ci --production && npm run build, dist/ folder created"
        },
        {
          "order": 4,
          "what": "Configure environment variables",
          "why": "12-factor app configuration via environment",
          "when": "Before starting the application",
          "how": "Set NODE_ENV=production, PORT, and app-specific config in ecosystem.config.js",
          "verify": "Environment variables accessible to application process",
          "success": true,
          "details": "added env section to ecosystem.config.js with NODE_ENV=production, PORT=3000"
        },
        {
          "order": 5,
          "what": "Deploy and start application",
          "why": "Run the application with your chosen method",
          "when": "After application is prepared",
          "how": "pm2 start ecosystem.config.js && pm2 save",
          "verify": "curl http://localhost:3000/health returns success",
          "success": true,
          "details": "pm2 start ecosystem.config.js, /health returns {\"status\":\"ok\"}"
        },
        {
          "order": 6,
          "what": "Configure process management and monitoring",
          "why": "Ensure application restarts on crash and is monitored",
          "when": "After initial deployment succeeds",
          "skip_if": "Orchestrator handles this",
          "how": "Configure restart policies and monitoring",
          "verify": "Kill the app process - it should restart automatically",
          "success": true,
          "details": "pm2 startup configured, tested kill -9 and app restarted in 2s"
        }
      ]
    },
    {
      "path": "staging-cluster (Docker)",
      "description": "Docker deployment on staging cluster",
      "status": "complete",
      "step_count": 6,
      "steps": [
        {
          "order": 1,
          "what": "Assess deployment environment",
          "why": "Node.js apps can run in many ways",
          "when": "Before deployment",
          "how": "Evaluate options based on infrastructure",
          "verify": "Deployment method chosen",
          "success": true,
          "details": "chose Docker for consistent environment with production"
        },
        {
          "order": 2,
          "what": "Install Node.js runtime",
          "why": "Required for PM2 and systemd deployments",
          "when": "If using PM2 or systemd deployment",
          "skip_if": "Using Docker/K8s",
          "how": "Install via package manager",
          "verify": "node --version shows v20.x",
          "success": true,
          "details": "using Docker, Node.js included in container image"
        },
        {
          "order": 3,
          "what": "Prepare application",
          "why": "Application needs dependencies and build artifacts",
          "when": "Before running the application",
          "skip_if": "Using pre-built container image",
          "how": "npm ci --production, npm run build",
          "verify": "Build artifacts present",
          "success": true,
          "details": "multi-stage Dockerfile builds image with npm ci && npm run build, final image 145MB"
        },
        {
          "order": 4,
          "what": "Configure environment variables",
          "why": "12-factor app configuration",
          "when": "Before starting the application",
          "how": "Set environment variables via docker run -e or env_file",
          "verify": "Environment variables accessible",
          "success": true,
          "details": "created .env.staging with all config, using --env-file in docker run"
        },
        {
          "order": 5,
          "what": "Deploy and start application",
          "why": "Run the application",
          "when": "After application is prepared",
          "how": "docker run -d --name myapp -p 3000:3000 myapp:latest",
          "verify": "curl http://localhost:3000/health returns success",
          "success": true,
          "details": "docker run -d --name api-staging -p 3000:3000 --env-file .env.staging myapp:v1.2.3"
        },
        {
          "order": 6,
          "what": "Configure process management and monitoring",
          "why": "Ensure application restarts on crash",
          "when": "After initial deployment succeeds",
          "skip_if": "Orchestrator handles this",
          "how": "Use --restart=unless-stopped",
          "verify": "Kill the app process - it should restart",
          "success": true,
          "details": "using --restart=unless-stopped, verified restart after docker stop/start"
        }
      ]
    },
    {
      "path": "prod-cluster (Kubernetes)",
      "description": "Production Kubernetes cluster with HPA",
      "status": "complete",
      "step_count": 6,
      "steps": [
        {
          "order": 1,
          "what": "Assess deployment environment",
          "why": "Node.js apps can run in many ways",
          "when": "Before deployment",
          "how": "Evaluate options based on infrastructure",
          "verify": "Deployment method chosen",
          "success": true,
          "details": "chose Kubernetes for auto-scaling and zero-downtime deployments"
        },
        {
          "order": 2,
          "what": "Install Node.js runtime",
          "why": "Required for PM2 and systemd deployments",
          "when": "If using PM2 or systemd deployment",
          "skip_if": "Using Docker/K8s",
          "how": "Install via package manager",
          "verify": "node --version shows v20.x",
          "success": true,
          "details": "using Kubernetes, runtime in container image"
        },
        {
          "order": 3,
          "what": "Prepare application",
          "why": "Application needs dependencies and build artifacts",
          "when": "Before running the application",
          "skip_if": "Using pre-built container image",
          "how": "Build and push container image to registry",
          "verify": "Image in registry",
          "success": true,
          "details": "CI/CD builds image, pushed to registry.company.com/api:v1.2.3"
        },
        {
          "order": 4,
          "what": "Configure environment variables",
          "why": "12-factor app configuration",
          "when": "Before starting the application",
          "how": "Create ConfigMap and Secret in Kubernetes",
          "verify": "ConfigMap and Secret exist in namespace",
          "success": true,
          "details": "created api-config ConfigMap and api-secrets Secret in prod namespace"
        },
        {
          "order": 5,
          "what": "Deploy and start application",
          "why": "Run the application",
          "when": "After application is prepared",
          "how": "kubectl apply -f deployment.yaml",
          "verify": "curl http://api-service/health returns success",
          "success": true,
          "details": "deployed 3 replicas, rolling update completed, /health returning 200"
        },
        {
          "order": 6,
          "what": "Configure process management and monitoring",
          "why": "Ensure application restarts on crash",
          "when": "After initial deployment succeeds",
          "skip_if": "Orchestrator handles this",
          "how": "K8s has built-in restart policies",
          "verify": "Kill a pod - it should be recreated",
          "success": true,
          "details": "liveness/readiness probes configured, HPA scales 3-10 replicas based on CPU"
        }
      ]
    }
  ]
}
Locations: 3

Locations

dev-server (PM2) complete

Single development server using PM2 for process management

Steps: 6
1 Assess deployment environment ✓
Why
Node.js apps can run in many ways - choose what fits your infrastructure
When
Before deployment
How
Evaluate options: PM2, systemd, Docker, or Kubernetes
Verify
Deployment method chosen based on infrastructure assessment
Result
✓ chose PM2 for simplicity, already familiar with ecosystem.config.js
2 Install Node.js runtime ✓
Why
Required for PM2 and systemd deployments
When
If using PM2 or systemd deployment
Skip If
Using Docker/K8s or Node.js already at required version
How
Install via package manager or nvm
Verify
node --version shows v20.x or higher
Result
✓ nvm install 20 && nvm use 20, shows v20.10.0
3 Prepare application ✓
Why
Application needs dependencies and build artifacts
When
Before running the application
Skip If
Using pre-built container image
How
npm ci --production, then npm run build if needed
Verify
node_modules exists, build artifacts present
Result
✓ npm ci --production && npm run build, dist/ folder created
4 Configure environment variables ✓
Why
12-factor app configuration via environment
When
Before starting the application
How
Set NODE_ENV=production, PORT, and app-specific config in ecosystem.config.js
Verify
Environment variables accessible to application process
Result
✓ added env section to ecosystem.config.js with NODE_ENV=production, PORT=3000
5 Deploy and start application ✓
Why
Run the application with your chosen method
When
After application is prepared
How
pm2 start ecosystem.config.js && pm2 save
Verify
curl http://localhost:3000/health returns success
Result
✓ pm2 start ecosystem.config.js, /health returns {"status":"ok"}
6 Configure process management and monitoring ✓
Why
Ensure application restarts on crash and is monitored
When
After initial deployment succeeds
Skip If
Orchestrator handles this
How
Configure restart policies and monitoring
Verify
Kill the app process - it should restart automatically
Result
✓ pm2 startup configured, tested kill -9 and app restarted in 2s
staging-cluster (Docker) complete

Docker deployment on staging cluster

Steps: 6
1 Assess deployment environment ✓
Why
Node.js apps can run in many ways
When
Before deployment
How
Evaluate options based on infrastructure
Verify
Deployment method chosen
Result
✓ chose Docker for consistent environment with production
2 Install Node.js runtime ✓
Why
Required for PM2 and systemd deployments
When
If using PM2 or systemd deployment
Skip If
Using Docker/K8s
How
Install via package manager
Verify
node --version shows v20.x
Result
✓ using Docker, Node.js included in container image
3 Prepare application ✓
Why
Application needs dependencies and build artifacts
When
Before running the application
Skip If
Using pre-built container image
How
npm ci --production, npm run build
Verify
Build artifacts present
Result
✓ multi-stage Dockerfile builds image with npm ci && npm run build, final image 145MB
4 Configure environment variables ✓
Why
12-factor app configuration
When
Before starting the application
How
Set environment variables via docker run -e or env_file
Verify
Environment variables accessible
Result
✓ created .env.staging with all config, using --env-file in docker run
5 Deploy and start application ✓
Why
Run the application
When
After application is prepared
How
docker run -d --name myapp -p 3000:3000 myapp:latest
Verify
curl http://localhost:3000/health returns success
Result
✓ docker run -d --name api-staging -p 3000:3000 --env-file .env.staging myapp:v1.2.3
6 Configure process management and monitoring ✓
Why
Ensure application restarts on crash
When
After initial deployment succeeds
Skip If
Orchestrator handles this
How
Use --restart=unless-stopped
Verify
Kill the app process - it should restart
Result
✓ using --restart=unless-stopped, verified restart after docker stop/start
prod-cluster (Kubernetes) complete

Production Kubernetes cluster with HPA

Steps: 6
1 Assess deployment environment ✓
Why
Node.js apps can run in many ways
When
Before deployment
How
Evaluate options based on infrastructure
Verify
Deployment method chosen
Result
✓ chose Kubernetes for auto-scaling and zero-downtime deployments
2 Install Node.js runtime ✓
Why
Required for PM2 and systemd deployments
When
If using PM2 or systemd deployment
Skip If
Using Docker/K8s
How
Install via package manager
Verify
node --version shows v20.x
Result
✓ using Kubernetes, runtime in container image
3 Prepare application ✓
Why
Application needs dependencies and build artifacts
When
Before running the application
Skip If
Using pre-built container image
How
Build and push container image to registry
Verify
Image in registry
Result
✓ CI/CD builds image, pushed to registry.company.com/api:v1.2.3
4 Configure environment variables ✓
Why
12-factor app configuration
When
Before starting the application
How
Create ConfigMap and Secret in Kubernetes
Verify
ConfigMap and Secret exist in namespace
Result
✓ created api-config ConfigMap and api-secrets Secret in prod namespace
5 Deploy and start application ✓
Why
Run the application
When
After application is prepared
How
kubectl apply -f deployment.yaml
Verify
curl http://api-service/health returns success
Result
✓ deployed 3 replicas, rolling update completed, /health returning 200
6 Configure process management and monitoring ✓
Why
Ensure application restarts on crash
When
After initial deployment succeeds
Skip If
Orchestrator handles this
How
K8s has built-in restart policies
Verify
Kill a pod - it should be recreated
Result
✓ liveness/readiness probes configured, HPA scales 3-10 replicas based on CPU