如何将 NestJS 容器化
今天,我将带你了解如何将 NestJS 应用容器化。这将帮助你将应用打包到一个容器中,使其能够在不同的环境中稳定运行。让我们开始吧!
步骤 1:设置 Dockerfile
首先,我们需要Dockerfile在 NestJS 项目的根目录下创建一个文件。该文件将包含构建 Docker 镜像的指令。
基本Dockerfile结构大概是这样的:
# Use Node.js version 20 as the base image
FROM node:20
# Set the working directory in the container
WORKDIR /usr/src/app
# Copy package.json and package-lock.json
COPY package*.json ./
# Install dependencies
RUN npm install
# Copy the rest of the application code
COPY . .
# Build the application
RUN npm run build
# Run the application
CMD ["node", "dist/main.js"]
此 Dockerfile 执行以下操作:
- 使用 Node.js 版本 20 作为基础镜像。
- 将工作目录设置为
/usr/src/app. - 复制
package.json到package-lock.json工作目录。 - 使用以下命令安装依赖项
npm install。 - 将应用程序的其余代码复制到容器中。
- 使用以下方式构建应用程序
npm run build。 - 指定运行应用程序的命令
node dist/main.js。
创建一个.dockerignore文件,将不必要的文件从 Docker 镜像中排除。
node_modules
npm-debug.log
dist
.git
.env
*.md
.gitignore
步骤 2:在本地测试 Docker 容器
现在,让我们在本地测试一下 Docker 镜像,确保一切运行正常。
构建 Docker 镜像:
在项目根目录下打开终端并运行:
docker build -t nest-app .
此命令构建 Docker 镜像并为其添加标签nest-app。
运行 Docker 容器:
镜像构建完成后,您可以使用以下命令运行它:
docker run -p 3000:3000 nest-app
此命令从镜像启动一个新容器nest-app,并将容器的 3000 端口映射到本地计算机的 3000 端口。
核实申请:
打开您的网络浏览器并访问http://localhost:3000。如果一切设置正确,您应该会看到您的 NestJS 应用程序正在运行。
步骤 3:优化生产
为了优化 Dockerfile 以适应生产环境,我们将进行一些更改以减小镜像大小并提高安全性。
使用 Alpine 节点镜像:
Alpine 镜像体积更小、效率更高。请将基础镜像更新为:
FROM node:20-alpine
设置 NODE_ENV 环境变量:
设置NODE_ENV为production优化应用程序以适应生产环境:
ENV NODE_ENV production
请使用npm ci以下方式代替npm install:
npm ci对于 Docker 构建等自动化环境来说,这种方式更可靠。替换RUN npm install为:
RUN npm ci
添加用户说明:
为了提高安全性,请以非 root 用户身份运行应用程序。在安装依赖项后添加以下命令:
USER node
使用多阶段构建:
多阶段构建允许你将构建环境和运行时环境分离,从而创建更小的最终镜像。以下是一个多阶段 Dockerfile 示例:
# Development stage
FROM node:20-alpine AS development
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci
COPY . .
USER node
# Build stage
FROM node:20-alpine AS build
WORKDIR /usr/src/app
COPY package*.json ./
COPY --from=development /usr/src/app/node_modules ./node_modules
COPY . .
RUN npm run build
ENV NODE_ENV production
RUN npm ci --only=production && npm cache clean --force
USER node
# Production stage
FROM node:20-alpine AS production
WORKDIR /usr/src/app
COPY --from=build /usr/src/app/node_modules ./node_modules
COPY --from=build /usr/src/app/dist ./dist
CMD ["node", "dist/main.js"]
该装置分为三个阶段:
development用于本地开发,包含所有依赖项。build构建用于生产环境的应用程序。production:运行生产构建的最后阶段。
步骤 4:重建并运行优化后的镜像
更新完成后Dockerfile,重新构建镜像:
docker build -t nest-app .
然后,运行新的优化容器:
docker run -p 3000:3000 nest-app
使用以下命令检查新图像的大小:
docker images
您应该会看到图像大小显著减小,从而提高生产效率。
常见问题排查
- 错误:找不到模块“webpack”:请确保您的基础镜像中使用的是正确的 Node.js 版本。例如,请使用
FROM node:20-alpine而不是FROM node:14-alpine。 - 错误:找不到 nest 命令:这通常是由于未安装 Nest CLI 导致的。在多阶段构建中,请确保从开发阶段复制
node_modules已安装 CLI 的目录。
使用不同的软件包管理器
如果你使用的是 pnpm 而不是 npm,你的Dockerfile配置会略有不同。以下是一个示例:
# Development stage
FROM node:20 AS development
RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
WORKDIR /usr/src/app
COPY pnpm-lock.yaml ./
RUN pnpm fetch --prod
COPY . .
RUN pnpm install
USER node
# Build stage
FROM node:20 AS build
RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
WORKDIR /usr/src/app
COPY pnpm-lock.yaml ./
COPY --from=development /usr/src/app/node_modules ./node_modules
COPY . .
RUN pnpm build
ENV NODE_ENV production
RUN pnpm install --prod
USER node
# Production stage
FROM node:20-alpine AS production
WORKDIR /usr/src/app
COPY --from=build /usr/src/app/node_modules ./node_modules
COPY --from=build /usr/src/app/dist ./dist
CMD ["node", "dist/main.js"]
将 Fastify 与 NestJS 结合使用
如果您使用的是 Fastify 而不是 Express,则需要修改您的main.ts配置以监听0.0.0.0:
import { NestFactory } from '@nestjs/core';
import {
FastifyAdapter,
NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter(),
);
await app.listen(process.env.PORT || 3000, '0.0.0.0');
}
bootstrap();
搞定!你现在拥有了一个针对生产环境优化的 Docker 化 NestJS 应用。如果你想部署你的 NestJS 应用,请访问sliplane.io。
谢谢,
乔纳斯
