部署与运维
生产环境:nest build 输出 dist,用进程管理器与反向代理部署。
将 NestJS 应用部署到生产环境,不仅需要构建出优化后的产物,还需配置合适的运行参数、进程管理、健康检查、日志聚合和安全策略。以下是各个关键环节的最佳实践。
一、构建:nest build 输出 dist 目录
NestJS CLI 内置了打包功能,可将 TypeScript 编译为 JavaScript 并输出到 dist 目录。
nest build
该命令会:
- 读取
tsconfig.json(通常为tsconfig.build.json)编译项目。 - 将生成的 JS 文件输出到
dist文件夹。 - 可选地支持 webpack 模式(
nest build --webpack),用于微服务或部署包优化,但多数情况下默认配置即可。
生产环境构建优化:
- 设置
NODE_ENV=production环境变量,使某些依赖(如 TypeORM、Mongoose)使用生产配置。 - 确保
tsconfig.build.json中compilerOptions.removeComments和declaration选项按需设置(生产可移除注释,不生成.d.ts)。 - 使用
--optimization标志启用 webpack 的优化(如代码压缩、作用域提升等),但仅在使用了--webpack时才生效。
二、生产环境 Node 配置
Node.js 运行时参数对稳定性和性能至关重要。
1. NODE_ENV=production
- 明确设置为
production,使 NestJS 和第三方库(如 TypeORM、Express)启用生产模式:- 禁用调试日志、缓存模板、减少错误堆栈细节。
- 某些库会进行性能优化(如连接池调优)。
2. 内存限制:--max-old-space-size
Node.js 默认内存限制约为 1.4GB(64位系统),对于大型应用可能不足。可通过参数调整老生代内存大小:
node --max-old-space-size=2048 dist/main.js
建议:
- 根据服务器可用内存和应用负载设置,通常设置为服务器内存的 70%~80%,避免 OOM Killer 介入。
- 在容器环境(Docker/K8s)中,应将此值与容器内存限制(
memory limit)匹配,预留一部分给其他进程。
3. 其他有用标志
--enable-source-maps:生产环境启用源码映射,便于错误堆栈定位(需确保 source map 文件不被泄露)。--trace-warnings:跟踪警告来源,辅助排查潜在问题。--max-http-header-size:若客户端发送较大头部,可适当增加默认 16KB 限制。
三、进程管理
保证 Node.js 进程在崩溃后自动重启、多核服务器负载均衡。
1. PM2(常用进程管理器)
安装并启动:
npm install -g pm2
pm2 start dist/main.js --name my-app --instances 2 --max-memory-restart 500M
常用配置(ecosystem.config.js):
module.exports = {
apps: [
{
name: "nest-app",
script: "dist/main.js",
instances: "max", // 启用所有 CPU 核心
exec_mode: "cluster", // 集群模式
max_memory_restart: "1G",
env: { NODE_ENV: "production" },
error_file: "./logs/err.log",
out_file: "./logs/out.log",
merge_logs: true,
kill_timeout: 5000, // 强制杀死前等待时间(秒)
listen_timeout: 3000, // 应用监听超时
},
],
};
2. Docker + Kubernetes(容器化)
Dockerfile 示例(多阶段构建,保证镜像小):
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
COPY . .
RUN npm run build
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "--max-old-space-size=512", "dist/main.js"]
Kubernetes 部署关键点:
- 设置
Deployment的replicas数量(水平扩展)。 - 添加
livenessProbe和readinessProbe(利用健康检查端点)。 - 使用
ConfigMap和Secret管理环境变量。 - 设置
resources.limits.memory,配合--max-old-space-size预留内存。
四、健康检查:@nestjs/terminus 模块
NestJS 官方提供的 Terminus 模块可以方便地集成健康检查端点,用于容器探针或负载均衡监控。
安装:
npm install @nestjs/terminus
@nestjs/terminus 没有 TerminusModule.forRoot({ healthChecks: {...} }) 这种配置式 API;正确用法是把 TerminusModule 直接导入模块,再用 HealthCheckService + 各类 HealthIndicator(HttpHealthIndicator、TypeOrmHealthIndicator、MemoryHealthIndicator、DiskHealthIndicator 等)在控制器中组合检查项:
// health.module.ts
import { Module } from "@nestjs/common";
import { TerminusModule } from "@nestjs/terminus";
import { HttpModule } from "@nestjs/axios";
import { HealthController } from "./health.controller";
@Module({
imports: [TerminusModule, HttpModule],
controllers: [HealthController],
})
export class HealthModule {}
// health.controller.ts
import { Controller, Get } from "@nestjs/common";
import {
HealthCheckService,
HealthCheck,
HttpHealthIndicator,
TypeOrmHealthIndicator,
MemoryHealthIndicator,
} from "@nestjs/terminus";
@Controller("health")
export class HealthController {
constructor(
private health: HealthCheckService,
private http: HttpHealthIndicator,
private db: TypeOrmHealthIndicator,
private memory: MemoryHealthIndicator,
) {}
// 就绪探针:检查依赖(数据库、下游服务等)是否可用
@Get("readiness")
@HealthCheck()
readiness() {
return this.health.check([
() => this.db.pingCheck("database", { timeout: 1500 }),
() => this.http.pingCheck("downstream-api", "https://api.example.com/ping"),
]);
}
// 存活探针:只做轻量自检,不依赖外部服务
@Get("liveness")
@HealthCheck()
liveness() {
return this.health.check([() => this.memory.checkHeap("memory_heap", 300 * 1024 * 1024)]);
}
}
@HealthCheck() 会让路由返回标准的 Terminus 响应格式:所有检查通过时状态码 200,任一检查失败则为 503。
在 Kubernetes 中使用:
livenessProbe:
httpGet:
path: /health/liveness
port: 3000
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /health/readiness
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
五、日志聚合
生产环境需要收集来自多个实例的日志,并集中分析。
1. 推荐使用结构化日志(如 pino 或 winston)
见前面“日志记录”章节,生产应输出 JSON 格式,便于工具解析。
2. 日志聚合方案
| 方案 | 适用场景 | 特点 |
|---|---|---|
| ELK Stack (Elasticsearch, Logstash, Kibana) | 大规模、高复杂度 | 功能强大,支持全文检索和可视化 |
| Loki + Grafana | 轻量级,与 Kubernetes 集成好 | 日志与 Prometheus 指标共享标签,查询高效 |
| Datadog | 商业 SaaS,全栈监控 | 开箱即用,集成 APM、日志、基础设施监控 |
实现方式:
- 将日志输出到 stdout/stderr,由容器运行时收集并转发到日志代理(如 Filebeat、Fluentd、Promtail)。
- 在代码中使用 JSON 格式打印:
this.logger.info({ reqId: uuid(), userId }, "User action");
- 确保使用异步日志驱动(如 pino),避免阻塞事件循环。
六、环境变量确保安全
禁止在代码中硬编码任何凭证、API 密钥、数据库密码等敏感信息。
1. 使用 .env 文件(本地开发)
配合 @nestjs/config 模块,但 .env 文件不应提交到版本控制。
2. 生产环境注入方式
- Docker/K8s:通过
env或secret对象注入。例如:
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
- PM2:在
ecosystem.config.js中设置env字段。 - 系统环境变量:直接在启动命令前设置(安全性较低,不推荐多租户环境)。
3. 使用密钥管理服务(Vault)
对于高安全要求场景,可集成 HashiCorp Vault、AWS Secrets Manager 或 Azure Key Vault,应用启动时动态获取密钥。
4. 校验环境变量
在应用启动时,使用 Joi 或 class-validator 验证所有必需的环境变量是否已设置且格式正确,避免运行时因缺失配置而崩溃。
// main.ts 或 config.module.ts
const requiredEnv = ["DB_HOST", "DB_PASSWORD", "API_KEY"];
requiredEnv.forEach((key) => {
if (!process.env[key]) throw new Error(`Missing env ${key}`);
});
总结表
| 环节 | 关键措施 |
|---|---|
| 构建 | nest build,设置 NODE_ENV=production,使用 webpack 优化(可选) |
| Node 配置 | --max-old-space-size 设置内存上限,开启 --enable-source-maps |
| 进程管理 | PM2 集群模式,或 Docker + K8s 编排(设置管理探针) |
| 健康检查 | @nestjs/terminus 提供 /health 端点,支持 liveness/readiness |
| 日志聚合 | 使用 JSON 格式日志,集成 ELK/Loki/Datadog 集中收集 |
| 环境变量安全 | 禁止硬编码,通过 Secrets、Vault 注入;启动时强制校验 |
遵循这些实践,可以确保 NestJS 应用在生产环境中稳定、安全、可观测。
参考文献
以下链接在编写时均可正常访问:
| 资料 | 说明 |
|---|---|
| NestJS 文档 | 官方 |
| Deployment | 本章主题 |
| Request lifecycle | 执行顺序 |
相关文章
认证与授权
认证(Authentication):确认「你是谁」(如 JWT、Session)。 - 授权(Authorization):确认「你能做什么」(如 RBAC、策略检查)。
缓存
@nestjs/cache-manager 统一缓存 API,存储实现可插拔。
提供者与服务
Service 是最常见的 Provider,封装业务逻辑。见 module。
守卫 (Guards) 与授权
守卫决定是否放行请求,常用于认证与授权。见 auth。
配置管理(Config 模块)
@nestjs/config 加载 .env 并提供 ConfigService。见 工程化 env。
数据库集成(以 TypeORM 为例)
Nest 通过 @nestjs/typeorm 等包集成 ORM;生产环境用 migration,慎用 synchronize。亦可选用 Prisma、MikroORM 等(见 官方 Database)。
Series
new
9 / 19