Introduction
Writing a Node.js app is only half the job — getting it running reliably in production requires keeping the process alive, restarting it after crashes, packaging it consistently, and choosing where it will run. This lesson covers three key pieces of deployment: process managers like PM2 that supervise your app, containerization with Docker that packages your app with its dependencies, and common hosting targets where deployed apps actually run.
Cricket analogy: Writing the winning shot is only half the job — you also need a team management structure to keep players fit for the next match (process managers), a standard kit bag that travels identically to every venue (containers), and a choice of stadium to actually play in (hosting).
Syntax
# Install PM2 globally
npm install -g pm2
# Start an app under PM2
pm2 start server.js --name my-api
# View running processes
pm2 list
# View logs
pm2 logs my-api
# Restart on file changes (dev) or after a deploy
pm2 restart my-api
# Keep PM2 running across server reboots
pm2 startup
pm2 saveExplanation
A plain node server.js process dies if it crashes or if the terminal session ends. Process managers like PM2 solve this by running your app as a background daemon, automatically restarting it on crash, capturing logs, and optionally running multiple instances in cluster mode for better CPU utilization. Containerization takes this further: a Docker image packages your application code, its exact Node.js version, and all npm dependencies into a single reproducible artifact that runs the same way on a laptop, a CI server, or production, eliminating 'it works on my machine' problems. Common hosting targets include platform-as-a-service providers (Heroku, Render, Railway) that handle infrastructure for you, container-based clouds (AWS ECS/Fargate, Google Cloud Run, Azure Container Apps) that run Docker images at scale, and self-managed virtual private servers (a plain VPS with PM2 and a reverse proxy like Nginx) for full control.
Cricket analogy: A single net-session batsman collapses the moment the coach leaves (plain node server.js dying with the terminal); a proper support staff (PM2) keeps players match-ready around the clock, substitutes an injured player automatically, and fields multiple net bowlers in rotation for better throughput (cluster mode); a standardized touring kit (Docker image) packs the exact bat, gloves, and training gear so a player performs identically at home or away; and choosing a venue ranges from a franchise-managed stadium (PaaS) to a fully self-run club ground with your own groundskeeper (VPS with Nginx).
Example
# Dockerfile for a Node.js Express app
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
ENV NODE_ENV=production
EXPOSE 3000
CMD ["node", "server.js"]Output
Running docker build -t my-api . followed by docker run -p 3000:3000 my-api produces a container that starts the Express server inside an isolated filesystem with only production dependencies installed. Because the image bundles a specific Node.js version and locked dependency tree (via npm ci), the same image behaves identically whether it is run locally, in a CI pipeline, or on a cloud container platform — removing most environment-related deployment surprises.
Cricket analogy: Running docker build then docker run -p 3000:3000 is like sealing a touring squad's exact kit — same bats, same gloves, no spare gear left in the bag (production-only dependencies) — so the team performs identically whether practicing at home, in a warm-up match, or the actual final, thanks to a locked equipment list (npm ci).
Key Takeaways
- Process managers like PM2 keep a Node.js app running, restart it on crashes, and can run it in cluster mode across CPU cores.
- Docker packages an app, its Node.js runtime, and its dependencies into a reproducible image that runs consistently across environments.
- npm ci with --omit=dev installs exact, locked dependency versions and skips devDependencies for smaller production images.
- Common hosting targets include PaaS providers (Heroku, Render), container platforms (AWS ECS, Cloud Run), and self-managed VPS setups.
- A reverse proxy (like Nginx) is commonly placed in front of a Node.js app to handle TLS termination, load balancing, and static file serving.
Practice what you learned
1. What is the main benefit of using a process manager like PM2 for a Node.js app in production?
2. What is the purpose of a Dockerfile in deploying a Node.js app?
3. Which command is recommended for installing dependencies in a production Docker image to ensure exact, locked versions?
4. Which of the following is an example of a container-based cloud hosting target for Node.js apps?
Was this page helpful?
You May Also Like
Environment Variables and Configuration
Learn how to manage configuration and secrets in Node.js apps using environment variables and dotenv.
Node.js Performance Optimization
Learn how to scale Node.js apps with the cluster module, avoid blocking the event loop, and apply caching strategies.
Securing Express Apps (Helmet, CORS, Rate Limiting)
Harden Express applications with secure HTTP headers, controlled cross-origin access, and rate limiting to mitigate common attacks.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentSpring Boot Study Notes
Java · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentDjango Study Notes
Python · 30 topics