Node.js项目中怎么优化docker镜像

发布时间:2021-08-03 10:44:29 作者:Leah
来源:亿速云 阅读:204

这篇文章给大家介绍Node.js项目中怎么优化docker镜像,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

Node 项目

简单写了一个自己用的 wechat-bot ,接下来就以这个项目演示怎么去优化 Docker 镜像

以下是我没有仔细研究 Docker 刚开始写的 Dockerfile 文件

FROM node:14.17.3

# 设置环境变量
ENV NODE_ENV=production
ENV APP_PATH=/node/app

# 设置工作目录
WORKDIR $APP_PATH

# 把当前目录下的所有文件拷贝到镜像的工作目录下 .dockerignore 指定的文件不会拷贝
COPY . $APP_PATH

# 安装依赖
RUN yarn

# 暴露端口
EXPOSE 4300

CMD yarn start

build 之后,如下图,我这个简单的 Node 程序镜像竟然有 1G 多,接下来我们将逐步去优化减少这个大小

Node.js项目中怎么优化docker镜像

优化前言

在优化之前,有些东西我们必须了解,解决问题的第一步就是先找出导致问题的原因

优化 Dockerfile

优化第一层 FROM node:14.17.3

方案一:使用 node 的 Alpine 版本

这也是绝多数人知道的优化镜像手段,Alpine 是一个很小的 Linux 发行版,只要选择 Node 的 Alpine 版本,就会有很大改进,我们把这一句改成指令改成 FROM node:14.17.4-alpine (可以去 dockerhub 查看 node 有哪些版本标签),build 后镜像大小如下图,瞬间从 1.06G 降到 238M,可以说是效果显著

Node.js项目中怎么优化docker镜像

还可以使用其它的基础小镜像,比如 mhart/alpine-node,这个还能再小,改成 FROM mhart/alpine-node:14.17.3 再试试,可以看到又小了 5M ,虽然不多,但是秉着能压榨一点是一点的“老板原则”,积少成多,极致压榨

Node.js项目中怎么优化docker镜像

方案二:使用纯净 Alpine 镜像手动装 Node

既然 Alpine 是最小的 Linux,那我们试下用纯净的 Alpine 镜像,自己再装 Node 试试

FROM alpine:latest

# 使用 apk 命令安装 nodejs 和 yarn,如果使用 npm 启动,就不需要装 yarn
RUN apk add --no-cache --update nodejs=14.17.4-r0 yarn=1.22.10-r0

# ... 后面的步骤不变

build 后看下图,只有 174M 了,又小了不少

Node.js项目中怎么优化docker镜像

结论就是不嫌麻烦追求极致就用方案二,从 1.06G 减少到 174M

减少层数、不经常变动的层提到前面去

下面是改写后的 Dockerfile

FROM alpine:latest

# 使用 apk 命令安装 nodejs 和 yarn,如果使用 npm 启动,就不需要装 yarn
RUN apk add --no-cache --update nodejs=14.17.4-r0 yarn=1.22.10-r0

# 暴露端口
EXPOSE 4300

# 设置环境变量
ENV NODE_ENV=production \
    APP_PATH=/node/app

# 设置工作目录
WORKDIR $APP_PATH

# 把当前目录下的所有文件拷贝到镜像的工作目录下 .dockerignore 指定的文件不会拷贝
COPY . $APP_PATH

# 安装依赖
RUN yarn

# 启动命令
CMD yarn start

这一步的优化,无论从镜像大小还是构建镜像速度都看不到明显的差别,因为改动的层内容少(体现不出来),但是可以查看到镜像的层是变少了的,可以自行试试查看镜像的层试试

减少镜像层数是“好老板”的传统优良习惯,不让“员工”浪费资源

package.json 提前提高编译速度

从下图可以看到每次我们 build 的时候最耗时的就是在执行 yarn 命令装依赖的时候,大部分时候我们只是改代码,依赖不变,这时候如果可以让这一步缓存起来,依赖没有变化的时候,就不需要重新装依赖,就可以大大改进编译速度

Node.js项目中怎么优化docker镜像

前面我们说了镜像构建时,是一层层构建,前一层是后一层的基础,既然是这样的话,我们就把 package.json 文件单独提前拷贝到镜像,然后下一步装依赖,执行命令装依赖这层的前一层是拷贝 package.json 文件,因为安装依赖命令不会变化,所以只要 package.json 文件没变化,就不会重新执行 yarn 安装依赖,它会复用之前安装好的依赖,原理讲清楚了,下面我们看效果

改变后的 Dockerfile 文件

FROM alpine:latest

# 使用 apk 命令安装 nodejs 和 yarn,如果使用 npm 启动,就不需要装 yarn
RUN apk add --no-cache --update nodejs=14.17.4-r0 yarn=1.22.10-r0

# 暴露端口
EXPOSE 4300

# 设置环境变量
ENV NODE_ENV=production \
    APP_PATH=/node/app

# 设置工作目录
WORKDIR $APP_PATH

# 拷贝 package.json 到工作跟目录下
COPY package.json .

# 安装依赖
RUN yarn

# 把当前目录下的所有文件拷贝到镜像的工作目录下 .dockerignore 指定的文件不会拷贝
COPY . .

# 启动命令
CMD yarn start

build 看下图,编译时间从 29.6s 到 1.3s,使用了缓存的层前面会有个 CACHED 字眼,仔细看下图可以看到

Node.js项目中怎么优化docker镜像

使用多阶段构建再次压榨镜像大小

多阶段构建这里不多说了,不了解的可以先搜相关资料了解

因为我们运行 node 程序是只需要生产的依赖和最终 node 可以运行的文件,就是说我们运行项目只需要 package.js 文件里 dependencies 里的依赖,devDependencies 依赖只是编译阶段用的,比如 eslint 等这些工具在项目运行时是用不到的,再比如我们项目是用 typescript 写的,node 是不能直接运行 ts 文件,ts 文件需要编译成 js 文件,运行项目我们只需要编译后的文件和 dependencies 里的依赖就可以运行,也就是说最终镜像只需要我们需要的东西,任何其他东西都可以删掉,下面我们使用多阶段改写 Dockerfile

# 构建基础镜像
    FROM alpine:3.14 AS base

    # 设置环境变量
    ENV NODE_ENV=production \
        APP_PATH=/node/app
    
    # 设置工作目录
    WORKDIR $APP_PATH

    # 安装 nodejs 和 yarn
    RUN apk add --no-cache --update nodejs=14.17.4-r0 yarn=1.22.10-r0

# 使用基础镜像 装依赖阶段
    FROM base AS install

    # 拷贝 package.json 到工作跟目录下
    COPY package.json ./

    # 安装依赖
    RUN yarn

# 最终阶段,也就是输出的镜像是这个阶段构建的,前面的阶段都是为这个阶段做铺垫
    FROM base

    # 拷贝 装依赖阶段 生成的 node_modules 文件夹到工作目录下
    COPY --from=install $APP_PATH/node_modules ./node_modules

    # 将当前目录下的所有文件(除了.dockerignore排除的路径),都拷贝进入镜像的工作目录下
    COPY . .

    # 启动
    CMD yarn start

细心的朋友会发现我这里有指定 alpine 版本,而上面都是用的 latest 版本,因为就在刚刚发现有个坑需要注意下,就是我们选择 alpine 版本的时候,最好不要选择 latest 版本,因为后面要装的软件版本可能会在 alpine 的 latest 版本没有对应软件的版本号,就会安装错误,我刚刚就翻车了,点击查看 alpine 版本下的包信息

Node.js项目中怎么优化docker镜像

build 后,我们看看镜像大小,上次的是 174M 再次降到 73.4M,极致压榨。镜像:”放过我把,我真的没有了“

Node.js项目中怎么优化docker镜像

讲解:

我把这个构建分成了三个阶段:

多阶段构建,最后生成的镜像只能是最后一个阶段的结果,但是,能够将前置阶段中的文件拷贝到后边的阶段中,这就是多阶段构建的最大意义。

关于Node.js项目中怎么优化docker镜像就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

推荐阅读:
  1. Docker 镜像操作
  2. 怎么创建Docker镜像

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

node.js docker

上一篇:Python3如何监控疫情

下一篇:如何解决某些HTML字符打不出来的问题

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》