A Nest application is an ordinary Node.js server: you compile TypeScript to JavaScript and run dist/main.js with Node. This chapter covers production builds, environment configuration, and deploying with a process manager or containers. Express apps deploy the same way.
Production build
npm run build runs nest build, compiling src into dist. The output runs on plain Node.js without the Nest CLI.
npm ci
npm run build
NODE_ENV=production node dist/main
# or the generated script
npm run start:prod
Production servers do not need dev dependencies: remove them after building with npm prune --omit=dev, or install with npm ci --omit=dev. Avoid running production with ts-node or nest start. An Express app without a compile step simply runs as node src/server.js.
Production configuration
Keep configuration out of code and pass it as environment variables: the port via PORT, database URLs and secrets via your platform's secret store or environment settings. Never bake a .env file into an image or repository. A production main.ts typically adds the following.
// src/main.ts
import { ValidationPipe } from "@nestjs/common";
import { NestFactory } from "@nestjs/core";
import helmet from "helmet";
import { AppModule } from "./app.module";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(helmet()); // security-related HTTP headers
app.enableCors({ origin: process.env.CORS_ORIGIN });
app.useGlobalPipes(new ValidationPipe({ whitelist: true }));
app.enableShutdownHooks(); // clean up on SIGTERM
await app.listen(process.env.PORT ?? 3000, "0.0.0.0");
}
bootstrap();
helmet (installed with npm i helmet) is Express middleware, and Nest uses it as is through app.use(). With enableShutdownHooks(), lifecycle hooks such as onModuleDestroy run when the container sends a termination signal, so database connections close cleanly. Behind a reverse proxy, enable Express's trust proxy setting to read the real client IP and protocol; in Nest, create the app with NestFactory.create<NestExpressApplication>() and call app.set("trust proxy", 1).
Running under a process manager
On a VM or bare server, you need something that restarts the process if it dies. PM2 is a popular Node.js process manager and can run one process per CPU core in cluster mode.
npm i -g pm2
pm2 start dist/main.js --name api -i max
pm2 logs api
pm2 save # remember the current process list
pm2 startup # start automatically after a reboot
A systemd service running node dist/main.js is another common choice. Put a reverse proxy such as Nginx in front to handle TLS and static files.
Deploying with containers
Containers let the same image run anywhere. A multi-stage Dockerfile separates the build from the runtime and keeps the image small.
FROM node:lts-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build && npm prune --omit=dev
FROM node:lts-alpine
WORKDIR /app
ENV NODE_ENV=production
COPY --from=build /app/package*.json ./
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
USER node
EXPOSE 3000
CMD ["node", "dist/main.js"]
List node_modules, dist, .env and .git in .dockerignore to keep the build context small and secrets out of the image. Inside a container, run node directly rather than PM2, and leave restarts and replicas to Docker, Kubernetes or your cloud's container service.
docker build -t my-api .
docker run -p 3000:3000 -e DATABASE_URL="postgres://user:pass@db:5432/app" my-api
Pre-deployment checklist
- Make sure
npm run build and the test suites pass in CI. - Validate required environment variables at startup, for example with the
validate option of ConfigModule.forRoot. - Run database migrations as part of the release and keep
synchronize off. - Expose a health check endpoint for load balancers and orchestrators (Nest offers
@nestjs/terminus). - Log to standard output and let the platform collect the logs.
Summary
- Build
dist with npm run build, run it with node dist/main, and ship only production dependencies. - Supply configuration through environment variables and add production settings such as Helmet, CORS and shutdown hooks in
main.ts. - Use PM2 or systemd on servers, and a multi-stage Dockerfile for containers.
- Express apps follow the same principles: environment variables, process management and containers.
Official documentation
0 comments
Sign in · Sign in to leave a comment.