前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何通过Dockerfile优化Nestjs构建镜像大小

如何通过Dockerfile优化Nestjs构建镜像大小

作者头像
阿珍
发布2022-08-17 11:27:56
2.5K0
发布2022-08-17 11:27:56
举报
文章被收录于专栏:用户9379088的专栏

原文开始

这是一篇手把手的教程,教你如何在制作nestjs镜像时,能够编写出一个优化生产依赖的Dockerfile

有了这个Dockerfile,无论是在本地开发环境,还是在容器环境都能很轻松完成部署

P.S 如果你想直接复制最终的Dockerfile,请直接跳到文章末尾

开始编写Dockerfile

每个镜像都可以视为一个单独的软件包,你可以通过编写Dockerfile告诉docker如何来打包镜像

让我们开始编写吧,首先,先创建一个空的文件

代码语言:javascript
复制
touch Dockerfile
复制代码

然后把我们的指令添加到Dockerfile里面,并且注释每一步是干什么

代码语言:javascript
复制
# 基础镜像
FROM node:18
# 创建一个应用目录
WORKDIR /usr/src/app
# 这个星号通配符意思是复制package.json和package-lock.json,复制到当前应用目录
COPY package*.json ./
# 安装应用依赖
RUN npm install
# 安装完毕后复制当前目录所有文件到镜像目录里面
COPY . . 
# 执行npm run build 后生成dist目录
RUN npm run build
# 使用打包后的镜像
CMD ["node","dist/main.js"]
复制代码

同样的,创建.gitignore文件,我们可以把那些不需要经过docker打包的文件给忽略掉

代码语言:javascript
复制
touch .dockerignore
复制代码

把一下文件给排除忽略掉

代码语言:javascript
复制
Dockerfile
.dockerignore
node_modules
npm-debug
.log
dist
复制代码

在本地测试下

如果你在本地安装了docker,可以在本地进行打包测试,让我们来瞧瞧是否如预期中那样打包镜像

在命令行中执行以下命令,当然,你也可以把nest-app-demo换成你想要的镜像名,需要注意的是,不要忘记后面的.号!

代码语言:javascript
复制
docker build -t nest-app-demo .
复制代码

接着你可以在你本机执行以下命令,查看是否已经成功打包了镜像

代码语言:javascript
复制
docker images
复制代码

噢,感谢上帝,已经成功打包成镜像了,可以看到我们的命名nest-app-demo就像只肥硕的土拨鼠静静的躺在镜像列表里面

代码语言:javascript
复制
docker images
REPOSITORY                   TAG       IMAGE ID       CREATED          SIZE
nest-app-demo               latest    004f7f222139   31 seconds ago   1.24GB

复制代码

紧接着让我们来把镜像给跑起来,映射到本机80端口,如果端口被占用可以使用其他端口

代码语言:javascript
复制
docker run -p 80:3000 nest-app-demo
复制代码

这时候你就在浏览器中输入http://localhost进行访问,可以看到容器正常启动。 如果你想删除那些正在运行的容器,可以使用以下命令进行删除

代码语言:javascript
复制
docker rm -f $(docker ps -aq)
复制代码

Dockerfile 生产环境优化

好了,现在我们对镜像包进行压缩了,因为可以看到,目前镜像大小是1.24G,噢,上帝,真是太大了!

让我们来看看之前编写的Dockerfile,看如何对它进行优化

使用Alpine node镜像

强烈推荐使用node:18-alpine 而不是node:18,使用alpine的镜像可以直接把镜像体积从1.24g减少到466MB!

添加 NODE_ENV 环境变量

很多依赖包会根据当前的NODE_ENV环境变量而进行判断是否优化压缩,所以我们可以在Dockerfile里面把环境变量加进去,设置为production

代码语言:javascript
复制
ENV NODE_ENV production
复制代码

顺便提一句,如果你不知道如何在Nestjs里面通过配置文件进行环境变量设置的话,可以看下这篇入门文章www.tomray.dev/nestjs-conf…

使用npm ci 而不是npm install

npm 比较推荐使用npm ci 而不是npm install 来打包镜像,至于原因可以点击这里查看docs.npmjs.com/cli/v8/comm…

"npm cinpm install很相似,除了当它用于自动化时,如测试平台,持续集成和部署————或者任何你想确保能有一个干净的依赖安装环境"

正好符合我们现在的情况,所以我们要使用npm ci来替换npm install

代码语言:javascript
复制
RUN npm ci
复制代码

使用User指令

默认情况下,Dockerfile会使用root权限来构建你的镜像,这会存在一定的安全风险,在这里,我们已经拥有一个叫node的用户,我们可以直接使用它

代码语言:javascript
复制
USER node
复制代码

当你在使用COPY指令时,添加标志以确保用户能够拥有正确的权限也是一种好做法,比如可以使用--chown=node:node

代码语言:javascript
复制
COPY --chown=node:node package*.json ./
复制代码

使用多阶段构建

Dockerfile中,你可以定义多阶段构建,这是一种通过多个镜像构建出最优镜像的方式,可以使得最后生成的镜像最小化

代码语言:javascript
复制
###################
# BUILD FOR LOCAL DEVELOPMENT
###################

FROM node:18-alpine As development

# ...开发环境构建说明

###################
# BUILD FOR PRODUCTION
###################

# 生产环境基础镜像
FROM node:18-alpine As build

# ... 这里是构建说明

###################
# PRODUCTION
###################

# 生产环境基础镜像
FROM node:18-alpine As production

# ... 你的生产环境构建说明


复制代码

上面是多阶段构建的3个阶段:

  1. development这是用于本地环境构建镜像时的阶段
  2. build 这是用于构建生产镜像的阶段
  3. production 复制构建完毕后的文件并且启动服务

如果你不需要在本地环境使用docker启动你的Nestjs应用,可以把前两个阶段合二为一

上述多阶段设置的好处在于,这样你就有了一个可以在本地开发中使用的Dockerfile(与docker-compose组合在一起)。同时创建一个用于生产的优化Docker镜像。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 原文开始
  • 开始编写Dockerfile
  • 在本地测试下
  • Dockerfile 生产环境优化
    • 使用Alpine node镜像
      • 添加 NODE_ENV 环境变量
        • 使用npm ci 而不是npm install
          • 使用User指令
            • 使用多阶段构建
            相关产品与服务
            容器镜像服务
            容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档