如何使用Docker部署NestJS应用

前端 潘老师 1周前 (04-16) 12 ℃ (0) 扫码查看

在进行NestJS应用部署时,使用Docker可以极大地提高部署效率和环境的一致性。下面,就为大家详细介绍如何使用Docker来部署NestJS应用。

一、准备工作

(一)创建Demo项目

首先,需要有一个NestJS项目作为示例。如果还没有安装nestjs cli,可以通过以下命令进行安装:

npm i -g @nestjs/cli

安装完成后,使用下面的命令创建一个名为nestjs - docker - demo的项目:

nest new nestjs-docker-demo

(二)尝试运行项目

项目创建完成后,执行以下命令启动测试环境,看看项目是否能够正常启动:

npm run start:dev

若项目成功启动,在浏览器中访问http://localhost:4000(这里端口号4000是示例,若使用默认配置,通常为3000,具体可根据实际情况调整),如果能看到“Hello World!”之类的页面内容,就说明项目启动成功。至此,一个可供部署的NestJS项目示例就准备好了。

二、打包过程中的注意事项

NestJS项目的打包操作比较简单,执行npm run build命令,项目就会借助其脚手架自动完成打包。不过,这里有个容易忽略的小问题需要注意。如果项目中创建了一些在生产环境不需要使用的自定义文件夹,在打包时可能会出现问题。

比如,正常的打包目录结构可能类似这样:

dist
├── app.controller.d.ts
├── app.controller.js
├── app.controller.js.map
├── app.module.d.ts
├── app.module.js
├── app.module.js.map
├── app.service.d.ts
├── app.service.js
├── app.service.js.map
├── main.d.ts
├── main.js
├── main.js.map
└── tsconfig.build.tsbuildinfo
node_modules
src
test

但要是在根目录创建了一个像scripts这样存放处理脚本命令的目录,打包后的目录结构可能就会变成这样:

NESTJS-DOCKER-DEMO
├── dist
│   └── scripts
├── src
├── tsconfig.build.tsbuildinfo
├── node_modules
├── scripts
├── test.ts
├── .gitignore
├── .prettierrc
├── eslint.config.mjs
└── nest-cli.json

这种情况下,当执行npm run start:prod(实际对应node dist/main命令)时,就可能会出现找不到对应模块的错误。为了解决这个问题,可以修改启动命令,或者在tsconfig.build.json文件中忽略该目录,配置如下:

{
  "extends": "./tsconfig.json",
  "exclude": ["node_modules", "test", "dist", "**/*spec.ts", "scripts"]
}

三、创建Docker镜像

(一)编写Dockerfile

要使用Docker部署NestJS应用,首先要为应用创建一个镜像。在项目的根目录下创建一个名为Dockerfile的文件,内容如下:

FROM node:22

WORKDIR /usr/src/app

COPY . .

RUN npm --registry https://registry.npmmirror.com
RUN npm run build

RUN rm -rf src

EXPOSE 4000

CMD ["npm", "run", "start:prod"]

下面逐行解释一下这段代码的含义:

  • FROM node:22:表示基于node版本为22的镜像作为基础镜像,后续的操作都在这个基础上进行。
  • WORKDIR /usr/src/app:设置在Docker容器中的工作目录,后续的文件操作等都在这个目录下执行。
  • COPY . .:将当前项目目录下的所有文件复制到Docker容器的工作目录中。
  • RUN npm --registry https://registry.npmmirror.com:通过指定的镜像源安装项目依赖。
  • RUN npm run build:执行项目的打包命令。
  • RUN rm -rf src:删除项目的源文件目录,因为打包后的文件已经包含了运行所需的内容,源文件在生产环境中可以不再保留,这样能减小镜像体积。
  • EXPOSE 4000:指定容器要监听的端口,这里设置为4000,实际使用时可根据项目需求调整。
  • CMD ["npm", "run", "start:prod"]:当容器启动时,执行npm run start:prod命令来启动应用。这里要注意RUNCMD的区别,RUN命令是在构建镜像时执行,而CMD命令是在启动容器时才执行。

完成Dockerfile的编写后,可以使用docker build -t nestjs-api .命令来测试是否能够成功创建镜像。

(二)解决Dockerfile构建问题

在构建镜像的过程中,可能会遇到构建失败的情况,例如出现Error: failed to solve: node:22: failed to resolve source metadata for docker.io这样的错误提示。为了避免这类问题,需要确保以下两点:

  • 确保已经使用docker login命令登录到Docker。
  • 保证所使用的Docker镜像源有效。下面分享几个常用的镜像源:
"registry-mirrors": [
  "https://registry.docker-cn.com",
  "https://docker.mirrors.ustc.edu.cn",
  "https://hub-mirror.c.163.com",
  "https://hub.geekery.cn",
  "https://dockerpull.com"
]

可以根据实际情况选择合适的镜像源,在Docker的配置中进行设置。

四、编写docker-compose.yml文件

虽然通过前面的操作已经可以创建并运行Docker镜像,但在实际部署中,通常还需要编写docker-compose.yml文件来进行更方便的管理和配置。

在项目根目录下创建docker-compose.yml文件,并编写以下内容:

services:
  nestjs_api:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - 4000:4000
    env_file:
      - .env.production
    volumes:
      - ./src:/usr/src/app/src
    networks:
      - backend

networks:
  backend:

下面对各个字段进行解释:

  • build:指定构建镜像的源,这里使用前面创建的Dockerfile来构建镜像。
  • ports:用于指定端口映射,将本地的4000端口映射到Docker容器内的4000端口,这样外部就可以通过访问本地4000端口来访问容器内的应用服务,实际使用时可根据需要修改端口号。
  • env_file:指定传递给应用的环境变量文件,这里使用.env.production文件,确保该文件包含项目运行所需的环境变量。
  • volumes:用于设置目录挂载,将本地的src目录挂载到Docker容器内的/usr/src/app/src目录,这样在本地对src目录的修改可以实时同步到容器内,方便开发和调试。
  • networks:指定服务所在的网络,这里设置为backend。如果项目中还有其他服务,比如mysql服务,只有当它们处于同一个网络时,nestjs应用才能访问mysql服务。

五、部署应用

完成上述所有文件的编写和配置后,将项目代码以及相关的Docker文件上传到服务器。然后在服务器上打开项目目录对应的终端,执行以下命令:

docker-compose --env-file .env.production up -d

这条命令会自动构建镜像并启动NestJS应用服务。执行命令时要注意指定正确的环境变量文件.env.production,确保其中包含项目运行所需的环境变量。

当服务启动成功后,就可以通过浏览器或者其他工具访问对应的API,以此来检查服务是否正常运行。

通过以上步骤,就可以成功地使用Docker部署NestJS应用了。在实际操作过程中,可能会遇到各种不同的问题,需要根据具体情况进行排查和解决。希望这篇文章能帮助大家顺利完成NestJS应用的Docker部署工作。


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/front/17395.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】