今天咱们来聊聊如何把一个 NestJS 应用程序 Docker 化。这样就能帮你把应用打包成一个可以在各种环境里稳定运行的 Docker 容器。咱们开始吧!
步骤 1:首先开始配置 Dockerfile
首先,你需要在 NestJS 项目的根目录下新建一个 Dockerfile
文件,这个文件会包含所有用于构建 Docker 镜像的指令。
一个基本的 Dockerfile
可能的样子是这样的。
# 基于 Node.js 20 版本的镜像
FROM node:20
# 设置工作目录
WORKDIR /usr/src/app
# 复制 package.json 和 package-lock.json
COPY package*.json ./
# 安装依赖
RUN npm install
# 复制应用程序的其他文件
COPY . .
# 构建
RUN npm run build
# 运行
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调试日志
npm-debug.log
# 构建输出目录
dist
# Git版本控制文件夹
.git
# 环境配置文件
.env
# Markdown文件
*.md
# Git忽略文件
.gitignore
切换到全屏,退出全屏
本地测试Docker容器:
现在让我们本地测试一下我们的这个 Docker 镜像,确保一切都像预期那样运行。
我们来构建 Docker 镜像吧:
打开你的终端,在项目根目录下运行如下命令:
运行 Docker 构建命令:
docker build -t nest-app . # -t 表示给镜像打标签(Nest 应用程序)
点击全屏按钮以进入全屏模式,然后再点击以退出全屏模式
这条命令构建 Docker 图像并用标签 nest-app
标记它。
运行Docker容器:
构建镜像之后,你可以用 docker run
命令运行该镜像。
docker run -p 3000:3000 nest-app
运行 Docker 容器,将宿主机的 3000 端口映射到容器的 3000 端口,并启动名为 nest-app 的应用程序。
全屏 退出全屏
这个命令基于 nest-app
镜像启动一个新容器,并将容器的 3000 端口映射到你本地的 3000 端口。
验证应用!
打开你的网页浏览器,在浏览器中输入 http://localhost:3000
。如果一切设置正确,你应该能看到你的 NestJS 应用程序已经启动了。
第三步:生产优化阶段
为了在生产环境中优化 Dockerfile,我们将做一些调整以减小镜像的大小并增强安全性。
使用 Node.js Alpine 镜像:
阿尔pine图像更小且更高效。将基础图像更新到指定的基础图像:
从 node:20-alpine 镜像开始
注:`FROM node:20-alpine` 是 Dockerfile 中的一个指令,用于指定基础镜像。
进入全屏 退出全屏
如何配置 NODE_ENV:
环境变量:
将 NODE_ENV
设置为 production
以优化应用程序在生产中的表现:
设置 NODE_ENV 为 'production'.
点击进入全屏模式,点击退出全屏模式
使用npm ci
而不是npm install
:
npm ci
在自动化环境中,如 Docker 构建中更为可靠。请将以下命令替换 RUN npm install
:
RUN npm ci
npm ci
切换到全屏 | 退出全屏
给用户添加指令了
用非 root 用户运行程序,这样更安全。安装完依赖项后,请做以下事情:
用户节点(User节点)
进入全屏 退出全屏
试试使用多阶段构建:
下面是一个例子。多阶段构建过程允许你通过分离构建和运行时环境来创建更小的最终镜像。这里有一个多阶段Dockerfile的示例:
# 开发环境
FROM node:20-alpine AS development
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci
COPY . .
USER node
# 构建环境
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
# 生产环境
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
后,请重新构建该镜像:
运行这个命令来构建名为nest-app的Docker镜像:docker build -t nest-app .
。在这里,nest-app
是你想要创建的Docker镜像的名称。
进入全屏,退出全屏
然后,启动新的优化容器:
docker run -p 3000:3000 nest-app
运行这个命令来启动Docker容器,将容器内的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
就会有点不一样。这里举一个例子。
# 开发环境
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 --production
COPY . .
RUN pnpm install
USER node
# 构建环境
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
# 生产环境
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
加油,
Jonas
共同學(xué)習(xí),寫下你的評論
評論加載中...
作者其他優(yōu)質(zhì)文章