Process Managers

Process Managers and Containers

node server.js in a terminal is not a deployment. Production needs something that starts the process on boot, restarts it when it dies, keeps its logs and replaces it during a deploy without dropping requests. Two answers dominate, solving the same problem at different altitudes.

PM2 29,762 (7.0.4, github.com/Unitech/pm2 (https://github.com/Unitech/pm2 43,298 )) is a supervisor that runs on the host. pm2 start server.js -i max forks one process per core through node:cluster (Clustering Across CPU Cores) and load-balances the port across them; pm2 reload app restarts workers one at a time so the port is never unserved; pm2 startup with pm2 save restores the process list after a reboot; pm2 monit gives a live dashboard. Configuration lives in an ecosystem.config.js, where the useful knobs are max_memory_restart and kill_timeout. Check the license first: the npm 2,036 package is AGPL-3.0.

Containers take the other route — one Node process per container, with the orchestrator doing the restarting, scaling and rolling deploys. Official images exist for every supported line: node:26-alpine, node:24-alpine (the Active LTS line) and node:22-alpine.

A small production image with a non-root userDockerfile
FROM node:24-alpine
ENV NODE_ENV=production
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev && npm cache clean --force
COPY . .
USER node
CMD ["node", "server.js"]

Four details separate a working container from a frustrating one. Copy package*.json and install before the source, so Docker 514 reuses the dependency layer when only your code changed. Use npm ci, which installs exactly what the lockfile says. Use the exec form of CMD: the shell form makes /bin/sh PID 1, which swallows SIGTERM and turns every deploy into a ten-second kill, so handle the signal (Signals and Graceful Shutdown) or run with docker run --init. And run as USER node, not root.

Pick one layer, not both. PM2 in cluster mode inside a container gives you two supervisors with different opinions about restarts, and hides worker crashes from the orchestrator meant to react to them.