【转载】只需简单两步,轻松缩减 Node.js 应用的镜像大小

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 两个简单的步骤可以将镜像大小从948 MB缩减到79 MB。

image

写在前面

在处理 Node.js应用程序时,我注意到部署镜像的时间有时候需要很长时间,远超我的预期。于是,我开始深入研究这个问题,并且发现只需两个步骤就可以让 948M 大小的 Docker 镜像缩减至 78.6M,从而减少部署时间、提升效率。

如下图所示,这就是我尝试的结果(948MB缩减至78.6MB):

image

初始化配置

该应用程序是一个典型的 Web 应用程序,它具有前端部分(React.js)和后端部分(在 Express.js 上的 Node.js 服务器)。构建过程包含以下4个步骤:

  • 构建 NPM;
  • 运行测试;
  • 构建 Docker 镜像;
  • 发布到 hub.docker.com ;

应用程序更改前的 Dockerfile (位于应用程序目录的根目录中),若下所示:

FROM node:8.10.0

RUN mkdir -p /usr/app/build
WORKDIR /usr/app 

COPY ./build /usr/app/build
COPY ./node_modules /usr/app/node_modules
COPY ./package.json /usr/app/package.json 

EXPOSE 3000 

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

该 Dockerfile 做了以下几件事:

  • /usr/app 设置为应用程序目录;
  • 将构建文件复制到应用程序目录;
  • 将所需的 Node.js 模块复制到应用程序目录;

步骤1: 将基础的 Node.js 镜像替换为缩减后的镜像(948MB缩减至206MB)

Node.js 镜像仓库为每个 Node.js 版本提供了若干个镜像标签。例如,8.10.0版本就有6个不同的镜像标签:

  • 8.10.0 – 266MB compressed
  • 8.10.0-alpine– 23MB compressed
  • 8.10.0-onbuild – 266MB compressed
  • 8.10.0-slim – 92MB compressed
  • 8.10.0-stretch – 343MB compressed
  • 8.10.0-wheezy– 202MB compressed

有趣的是这个 alpine 版本。这是一个最小的可用镜像,因为它基于 Alpine Linux 项目。Alpine 使用的是 musl libc 而不是内部的 glibc ,但 Node.js 通常在典型的开发者系统中使用后者(glibc)。这可能会破坏您使用的一些函数库,但是我的基于 Express.js 的应用程序并没有问题。如下所示,切换到 alpine:

# change the first line from:
FROM node:8.10.0

# to:
FROM node:8.10.0-alpine

接下来,运行docker build 命令。在我的案例中,镜像的大小已经缩减到206MB,比初始大小减少了78%!

步骤2:使用 NPM --production 标签(206 MB缩减至79 MB)

默认情况下, npm install 将安装所有依赖项,包括 devDependencies 部分。有了 --production 标签,我们就可以从 package.json 文件中仅安装所需的依赖项。在 devDependencies 部分中,我保留了构建系统、测试工具和一些其它的开发工具。我习惯于将 React.js 函数库和其它的 UI 依赖项一起保留在 package.json 文件中,但是它看起来是不正确的,因为我有 webpack 来生成所有的 UI 依赖项。因此,正确的方法是将所有不会直接用于在生产服务器上,也不会直接用于在 devDependencies 部分上的依赖项移除。

**原则是:如果依赖项只是在构建期间需要用到,请将它移到 devDependencies 部分。
**
我没有为服务器文件打包,所以我将所有服务器依赖项保留在依赖项部分中,就像以前一样。这意味着工作流程应包含以下步骤:

  • 构建 UI 包;
  • 将UI包复制到 Docker 镜像;
  • 将服务器文件复制到 Docker 镜像;
  • 将 package.json 文件复制到 Docker 镜像;
  • 在镜像中执行 npm install --production 命令;

我得到的 Dockerfile 的最终版本,如下所示:

FROM node:8.10.0-alpine

RUN mkdir -p /usr/app/build
WORKDIR /usr/app

COPY ./build /usr/app/build
COPY ./package.json /usr/app/package.json

RUN cd /usr/app && npm install --production

EXPOSE 3000

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

再次运行docker build命令。在我的案例中,镜像大小缩减至79M,这一次比初始大小减少了91%!

结论

两个简单的步骤可以将镜像大小从948 MB缩减到79 MB。现在容器部署过程所需的时间减少了很多。在hub.docker.com 上被压缩的镜像大小看起来更好!

image

P.S. 原文由Anton Fisher发布在个人博客上
Reducing Docker image size of a Node.js application


更多信息

您可以使用阿里云容器+镜像服务,应用的部署发布可以使用免费的CodePipeline(支持Go Java Node.js和Php项目)。And 最重要的是,您可以使用免费的Node.js性能平台。您可以移步文章《六年打怪升级,一路披荆斩棘,只为没有难用的Node.js

目录
相关文章
|
1月前
|
开发框架 前端开发 JavaScript
使用JavaScript、jQuery和Bootstrap构建待办事项应用
使用JavaScript、jQuery和Bootstrap构建待办事项应用
11 0
|
1月前
|
自然语言处理 JavaScript 前端开发
探索JavaScript中的闭包:理解其原理与实际应用
探索JavaScript中的闭包:理解其原理与实际应用
17 0
|
2月前
|
资源调度 JavaScript
nodeJS 的 npm 设置国内高速镜像之淘宝镜像的方法
nodeJS 的 npm 设置国内高速镜像之淘宝镜像的方法
1335 2
|
24天前
|
JavaScript 前端开发 算法
js开发:请解释什么是虚拟DOM(virtual DOM),以及它在React中的应用。
虚拟DOM是React等前端框架的关键技术,它以轻量级JavaScript对象树形式抽象表示实际DOM。当状态改变,React不直接操作DOM,而是先构建新虚拟DOM树。通过高效diff算法比较新旧树,找到最小变更集,仅更新必要部分,提高DOM操作效率,降低性能损耗。虚拟DOM的抽象特性还支持跨平台应用,如React Native。总之,虚拟DOM优化了状态变化时的DOM更新,提升性能和用户体验。
20 0
|
9天前
|
存储 JavaScript 前端开发
Angular 应用 node_modules 子文件夹 @types 的作用介绍
Angular 应用 node_modules 子文件夹 @types 的作用介绍
12 1
|
1天前
|
开发框架 前端开发 JavaScript
采用C#.Net +JavaScript 开发的云LIS系统源码 二级医院应用案例有演示
技术架构:Asp.NET CORE 3.1 MVC + SQLserver + Redis等 开发语言:C# 6.0、JavaScript 前端框架:JQuery、EasyUI、Bootstrap 后端框架:MVC、SQLSugar等 数 据 库:SQLserver 2012
|
20天前
|
开发框架 JavaScript 前端开发
描述JavaScript事件循环机制,并举例说明在游戏循环更新中的应用。
JavaScript的事件循环机制是单线程处理异步操作的关键,由调用栈、事件队列和Web APIs构成。调用栈执行函数,遇到异步操作时交给Web APIs,完成后回调函数进入事件队列。当调用栈空时,事件循环取队列中的任务执行。在游戏开发中,事件循环驱动游戏循环更新,包括输入处理、逻辑更新和渲染。示例代码展示了如何模拟游戏循环,实际开发中常用框架提供更高级别的抽象。
11 1
|
1月前
|
JavaScript 前端开发
HTML JS 应用
HTML JS 应用
19 3
|
1月前
|
JavaScript 前端开发 算法
Vue.js的单向数据流:让你的应用更清晰、更可控
Vue.js的单向数据流:让你的应用更清晰、更可控
|
1月前
|
JavaScript 前端开发 API
Vue.js 深度解析:nextTick 原理与应用
Vue.js 深度解析:nextTick 原理与应用