利用Dockerfile优化Nestjs构建镜像大小详情

目录
  • 前言
  • 原文开始
  • 开始编写Dockerfile
  • 在本地测试下
  • Dockerfile 生产环境优化
    • 使用Alpine node镜像
    • 添加 NODE_ENV 环境变量
    • 使用npm ci 而不是npm install
    • 使用User指令
    • 使用多阶段构建
  • 最终的Dockerfile

前言

众所周知,Node.js项目在部署的时候,无论是在虚拟机部署,还是使用docker进行部署,无非都是要先npm install,然后把整个node_modules丢上去,最后启动服务

但是有些开发依赖在生产环境部署的时候是不需要的。如果能每次打包只打包生产依赖,那就极大的减少node_modules大小

所以当时我在优化公司的nestjs项目时,苦苦寻找解决方案,就找到了这一篇文章,英文版原本在这里 www.tomray.dev/nestjs-dock…

原文开始

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

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

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

开始编写Dockerfile

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

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

touch Dockerfile

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

# 基础镜像
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打包的文件给忽略掉

touch .dockerignore

把一下文件给排除忽略掉

Dockerfile
.dockerignore
node_modules
npm-debug
.log
dist

在本地测试下

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

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

docker build -t nest-app-demo .

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

docker images

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

docker images
REPOSITORY                   TAG       IMAGE ID       CREATED          SIZE
nest-app-demo               latest    004f7f222139   31 seconds ago   1.24GB

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

docker run -p 80:3000 nest-app-demo

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

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

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

RUN npm ci

使用User指令

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

USER node

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

COPY --chown=node:node package*.json ./

使用多阶段构建

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

###################
# 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个阶段:

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

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

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

如果你对使用Docker Compose的多阶段Dockerfile进行本地开发(热加载)有兴趣,可以点击看这篇文章www.tomray.dev/nestjs-dock…

最终的Dockerfile

通过上述使用的方案进行优化后,最终的Dockerfile如下,他可以帮助我们构建出最优的镜像

###################
# BUILD FOR LOCAL DEVELOPMENT
###################

FROM node:18-alpine As development

# 创建应用目录
WORKDIR /usr/src/app

# 复制依赖清单到容器镜像里.
# 这个星号通配符意思是复制package.json和package-lock.json,复制到当前应用目录.
# 首先复制这个选项可以防止在每次代码更改时重新运行npm install.
COPY --chown=node:node package*.json ./

# 使用npm ci来安装依赖而不是npm install
RUN npm ci

# 复制安装后的依赖包到当前目录下
COPY --chown=node:node . .

# 使用指定的用户而不是root权限用户
USER node

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

FROM node:18-alpine As build

WORKDIR /usr/src/app

COPY --chown=node:node package*.json ./

# 我们需要通过Nest CLI 来执行npm run build,这是个开发依赖,然后把安装后依赖全部复制到指定目录
COPY --chown=node:node --from=development /usr/src/app/node_modules ./node_modules

COPY --chown=node:node . .

# 执行打包命令
RUN npm run build

# 设置生产环境变量
ENV NODE_ENV production

# 运行' npm ci '会删除现有的node_modules目录,并传入——only=production确保只安装了生产依赖项。这确保node_modules目录尽可能优化
RUN npm ci --only=production && npm cache clean --force

USER node

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

FROM node:18-alpine As production

# 将生产依赖和打包后的文件复制到指定目录下
COPY --chown=node:node --from=build /usr/src/app/node_modules ./node_modules
COPY --chown=node:node --from=build /usr/src/app/dist ./dist

# 启动服务
CMD [ "node", "dist/main.js" ]

可以看到,最后打包的镜像只有189MB大小

REPOSITORY                   TAG       IMAGE ID       CREATED          SIZE
nest-cloud-run               latest    004f7f222139   31 seconds ago   189MB

到此这篇关于利用Dockerfile优化Nestjs构建镜像大小详情的文章就介绍到这了,更多相关Dockerfile优化Nestjs内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Docker部署java项目的详细步骤(利用Dockerfile方式)

    目录 前言 1. 首先找一个你熟悉的目录下创建一个目录upload(这个目录可以随便),并把java的linux和jar包上传进去 2. 创建一个名为 Dockerfile文件 3. 以上命令配置完成后,即可输入命令进行build,然后回车 4 . 启动该容器 5. 访问地址 总结 前言 如何将java项目部署到Docker中呢,这里以一个springboot为例 以下命令全部都是以linux为基础的 1. 首先找一个你熟悉的目录下创建一个目录upload(这个目录可以随便),并把java的li

  • 使用Dockerfile实现数据卷的挂载问题(推荐)

    大家好,我们今天分享使用Dockerfile来实现数据卷的挂载 首先呢,要了解一下什么是Dockerfile Dockerfile就是 一个可以用来构建镜像的文件,可以理解为一个脚本文件 可以通过这个脚本文件自定义生成一个我们想要的镜像,镜像都是一层一层的,里面的每一条命令就是一层 创建一个目录 root@localhost home]# mkdir docker-vl2 编辑这样这样的一个文件 root@localhost docker-vl2]# vim dockerfile01 FROM

  • Dockerfile文件详解

    目录 什么是dockerfile? Dockerfile的基本结构 Dockerfile文件说明 FROM MAINTAINER RUN shell执行 exec执行 ADD COPY CMD ENTRYPOINT LABEL ENV EXPOSE VOLUME WORKDIR USER ARG ONBUILD 以下是一个小例子: 什么是dockerfile? Dockerfile是一个包含用于组合映像的命令的文本文档.可以使用在命令行中调用任何命令. Docker通过读取Dockerfile中

  • Python Web App开发Dockerfiles编写示例

    目录 TL;DR 内容 1. 简单的 Dockerfile 样例 2. 使用 Gunicorn 实现热更新 3. 运行一个单文件 python 脚本 4. 部署静态文件 5. 生产环境中的直接构建 6. 生产环境中的多级构建 原文地址:How to write Dockerfiles for Python Web Apps 原文作者:Praveen Durairaj 译文出自:https://github.com/xitu/gold-miner 本文永久链接:https://github.com

  • docker通过Dockerfile构建mysql镜像的方法

    构建Dockerfile ,路径 /docker/mysql FROM hub.c.163.com/library/mysql:5.7 #作者信息 MAINTAINER hu "***@qq.com" #修改编码方式 RUN echo "character-set-server=utf8" >> /etc/mysql/mysql.conf.d/mysqld.cnf RUN service mysql restart EXPOSE 3306 到Docker

  • 如何使用 Dockerfile 创建一个简单容器

    目录 Dockerfile 写一个 Dockerfile 优化 Dockerfile container shell Dockerfile Dockerfile 是用于指导 docker 创建自定义 image 的一系列指令,是用于创建 image 的蓝图. 现在有一个简单的 node 项目( 其中Dockerfile 是后面加的,初始项目没有此文件): 要运行此代码,一般的做法是,先在本机安装 node,然后在项目文件夹中先后运行: npm install 以及: node server.js

  • dockerfile指令构建docker镜像的示例代码

    目录 初识Dockerfile 编写一个自己的docker 镜像: DockerFile docker build . 命令 查看镜像是如何生成的 初识Dockerfile Dockerfile就是用来构建docker镜像的构建文件!命令脚本! 通过这个脚本可以生成镜像,镜像是一层层的,脚本是一行行的命令,每行命令都是一层 dockerfile是面向开发的,我们以后要发布项目,作镜像,就需要编写dockerfile文件,这个文件十分简单. Dockerfile镜像之间成为了企业交付的标准,必须掌

  • docker 编辑Dockerfile 添加php7.2 acpu的问题

    目录 docker 编辑Dockerfile 添加php7.2 acpu Dockerfile基于镜像php:7.2-fpm构建自定义php7.2镜像 docker-php-ext 方式安装 pecl方式安装 docker 编辑Dockerfile 添加php7.2 acpu 直接编辑Dockerfile ARG INSTALL_APCU=false RUN if [ ${INSTALL_APCU} = true ]; then \     # Install Php apcu Extensio

  • 利用Dockerfile优化Nestjs构建镜像大小详情

    目录 前言 原文开始 开始编写Dockerfile 在本地测试下 Dockerfile 生产环境优化 使用Alpine node镜像 添加 NODE_ENV 环境变量 使用npm ci 而不是npm install 使用User指令 使用多阶段构建 最终的Dockerfile 前言 众所周知,Node.js项目在部署的时候,无论是在虚拟机部署,还是使用docker进行部署,无非都是要先npm install,然后把整个node_modules丢上去,最后启动服务 但是有些开发依赖在生产环境部署的

  • 使用Docker多阶段构建来减小镜像大小的方法

    本文讲述了如何通过 Docker 的多阶段构建功能来大幅度减小镜像大小,适用于需要在 Dockerfile 中构建程式(如 javac),且需要另外安装编译工具链的镜像.(如 Java) 先来学习单词(本文全部采用中文词汇,如需查询外文文档可对照该词汇表.理论上个人不赞成翻译术语): multi-stage 多阶段 build 构建 image 镜像 stage 阶段 再来看一下效果: 原 110M+,现 92M. 对比一下 Dockerfile 优化前 Dockerfile: FROM ope

  • 优化 Docker 镜像大小常见的方式

    平时我们构建的 Docker 镜像通常比较大,占用大量的磁盘空间,随着容器的大规模部署,同样也会浪费宝贵的带宽资源.本文将介绍几种常用的方法来优化 Docker 镜像大小,这里我们使用 Docker Hub 官方上的 Redis 镜像进行说明. 手动管理 我们能够直接想到的方法就是直接修改官方的 Redis 镜像 Dockerfile 文件,手动删除容器运行后不需要的组件,然后重新构建一个新镜像.这种方法理论上是可行的,但是容易出错,而且效果也不是特别明显.主要是不能和官方的镜像实时同步. 多阶

  • docker使用Dockerfile构建镜像的方法

    构建镜像 前面我们使用各种镜像进行测试演示,很多情况下我们是需要自己的镜像,满足自己业务需要的镜像,这就需要我们能够定制自己需要的镜像,构建 Docker 镜像有以下两种方法. 使用 docker commit 命令. 使用 docker build 命令和 Dockerfile 构建文件. 现在我们不推荐使用 docker commit 命令,而应该使用更灵活.更强大的 Dockerfile 来构建 Docker 镜像. 1.使用 commit 命令构建 docker commit 命令是创建

  • Docker如何使用Dockerfile构建镜像

    Dockfile是一种被Docker程序解释的脚本,Dockerfile由一条一条的指令组成,每条指令对应Linux下面的一条命令.Docker程序将这些Dockerfile指令翻译真正的Linux命令.Dockerfile有自己书写格式和支持的命令,Docker程序解决这些命令间的依赖关系,类似于Makefile.Docker程序将读取Dockerfile,根据指令生成定制的image.相比image这种黑盒子,Dockerfile这种显而易见的脚本更容易被使用者接受,它明确的表明image是

  • Dockerfile文件编写及构建镜像命令解析

    目录 指令解析 简单的Dockerfile文件 Build命令添加dockerfile参数 构建镜像 构建容器并端口映射启动 镜像上传到远程镜像仓库 部署 指令解析 FROM # 基于什么镜像 WORKDIR # 指定工作路径,没有就创建目录 ------ COPY # 拷贝,文件地址 ADD # 拷贝,也可以是文件地址,也可以是url网络资源 ------ RUN # 运行shell语句 ------ ENTRYPOINT 1.运行容器时,执行的脚本.可以是json数据指定,也可以是shell

  • Docker镜像构建原理解析(不装docker也能构建镜像)

    在devops流程里面 构建镜像是一个非常重要的过程,一般构建镜像是写dockerfile文件然后通过docker client来构建的image. docker client 会先检查本地有没有image,如果没有帮你 从镜像仓库 pull 下来 然后解析你写的dockerfile构建新的image. 本文带你了解 pull 命令 背后是怎么做的? build 命令 背后是怎么做的? 下篇文章带你解析: 如果我不用docker 我如何构建一个镜像? 我们以微软的aspnet2.2为基础构建一个

  • Docker Compose+Nestjs构建Dapr Redis发布订阅分布式应用

    目录 Dapr(分布式应用程序运行时)介绍 实战 Dapr 的 Redis 发布/订阅应用 1. 创建项目 2. 创建 Dapr Placement 服务 3. 创建 Redis Publish 服务 4. 创建 Dapr Pub-Sub 组件 5. 创建 Redis Dapr Sidecar 6. 创建 NestJS Server 7. 为 NestJS 订阅服务器创建 Dockerfile 8. 将 NestJS 订阅服务添加到 docker-compose 文件 9. 创建 Dapr 订阅

  • 利用Docker制作Nginx+PHP镜像的步骤详解

    前言 这篇文章给大家介绍的是使用Docker制作nginx+php的镜像,本文里的镜像是centos + nginx 1.9.7 + php 5.6.14,下面话不多说,直接看实现的步骤吧. 1.首先下载到nginx和php: nginx-1.9.5.tar.gz 下载:http://nginx.org/en/download.html php-5.6.14.tar.gz   下载:>http://php.net/downloads.php 2.以及扩展包so: memcache-2.2.4.t

  • 基于alpine用dockerfile创建的tomcat镜像的实现

    1.下载alpine镜像 [root@docker43 ~]# docker pull alpine Using default tag: latest Trying to pull repository docker.io/library/alpine ... latest: Pulling from docker.io/library/alpine 4fe2ade4980c: Pull complete Digest: sha256:621c2f39f8133acb8e64023a94dbd

随机推荐