我平时写 API 项目会选用 NestJS + TypeScript 来搭建,生态丰富,类 Spring 的架构使得生产环境有非常稳健的架构。如果你是从 Express, Koa 那个年代过来的,NestJS 会让你直呼真香,对于写 API 来说,相比 Nextjs 框架,NestJS 才是构建 API 最佳的 Nodejs 框架。
部署的时候,选择 Dokploy 的基于 Docker 形式的构建和部署,对接 Github ,可以实现自动化的构建部署管理,如果不用 Docker 形式,我会选择 PM2 来进行配置。
Dokploy 基础入门,可以参考 # Dokploy 托管你的全栈应用 进行 Github 的连接和 Database 的配置。

NestJS 项目代码

使用 nestjs 脚手架构建完项目之后,文件结构如下,创建 Dockerfile 和 docker-compose.yml 文件。

├── .dockerignore
├── .env
├── .git
├── .gitignore
├── .prettierrc
├── .vscode
├── Dockerfile
├── README.md
├── dist
├── docker-compose.yml
├── eslint.config.mjs
├── nest-cli.json
├── node_modules
├── package.json
├── pnpm-lock.yaml
├── src
├── test
├── tsconfig.build.json
└── tsconfig.json

Dockerfile 配置文件

# -------- Base: install deps --------

FROM node:24 AS deps

WORKDIR /app

# 启用 corepack 以使用 pnpm

RUN corepack enable

# 只拷贝依赖清单,最大化缓存命中

COPY package.json pnpm-lock.yaml ./

RUN pnpm install --frozen-lockfile

# -------- Build: compile NestJS --------

FROM node:24 AS builder

WORKDIR /app

RUN corepack enable

# 先带上依赖,再拷贝源码

COPY --from=deps /app/node_modules ./node_modules

COPY . .

# 如果使用 Prisma/Swagger/其他代码生成,请在这里做:

# RUN pnpm prisma generate

# 编译(默认执行 nest build)

RUN pnpm build

# -------- Runtime: slim prod image --------

FROM node:24 AS runner

WORKDIR /app

RUN corepack enable

ENV NODE_ENV=production

# 可选:更友好的堆栈与日志

ENV NODE_OPTIONS=--enable-source-maps

# 仅安装生产依赖,镜像更小

COPY package.json pnpm-lock.yaml ./

RUN pnpm install --prod --frozen-lockfile

# 拷贝编译产物

COPY --from=builder /app/dist ./dist

# 如果你的应用依赖运行时文件(如 public、views、.env.production),请在这里拷贝:

# COPY --from=builder /app/public ./public

EXPOSE 5555

CMD ["node", "dist/main.js"]

docker-compose.yml

services:
	api:
		build:
			context: .
			args:
				APP_NAME: ctree-saas-api
	env_file: [.env]
	ports:
		# - "${API_HOST_PORT}:${API_PORT}" 如果设置动态映射,可这用这样的配置
		- '6801:5555'	
	environment:
		PORT: 5555
		# 数据库连接串(容器间用服务名 db 作为主机名)
		DATABASE_URL: 'postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}'
	restart: unless-stopped

.dockerignore

# 依赖
node_modules
npm-debug.log*
pnpm-debug.log*

# 构建输出
dist
build

# 环境变量
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
  
# 日志
logs
*.log
  
# 测试覆盖率
coverage

# IDE
.vscode
.idea

# Git
.git
.gitignore
  
# Docker
Dockerfile
.dockerignore
docker-compose*.yml

# 其他
README.md
.DS_Store
Thumbs.db

Dokploy 部署

创建 Project,如图

CleanShot 2025-11-19 at 20.04.53@2x.png

选择 Create Service -> Compose 的形式来创建项目,如果用 Application ,就没有 docker compose 的配置方式了

CleanShot 2025-11-19 at 20.14.11@2x.png

连接 Github Account,选择对应的 Repo,记得把 Compose Path 文件位置填写上,Trgger Type 设置为 On Push,这样当往 Main 分支推送代码的时候,就能自动触发重新构建并且部署了

CleanShot 2025-11-19 at 20.17.45@2x.png

在 Environment 里面配置项目的所有环境变量,线上环境变量只在这里统一管理,本地环境变量在 .env, .env.local 里面,不会泄露

CleanShot 2025-11-19 at 20.18.40@2x.png

Domain 里面添加自己自定义的域名,配置完成后,记得在域名厂商那里配置对应的 A 记录映射。

CleanShot 2025-11-19 at 20.19.15@2x.png

配置如图,把 HTTPS 勾上,使用 Let's Encrypt 来自动创建和续费证书。

CleanShot 2025-11-19 at 20.20.15@2x.png

配置完成之后,即可点击 Deploy 进行构建部署

CleanShot 2025-11-19 at 20.21.13@2x.png

构建的过程可以看到日志,如果失败了都可以在 Logs 面板进行查看调试

CleanShot 2025-11-19 at 20.24.33@2x.png

Bingo! 打包完成后,访问你刚才配置的域名就能看到服务运行在公网了。