使用构建缓存优化 Docker 镜像构建

使用构建缓存优化 Docker 镜像构建

目录

  • 实践
  • 构建应用程序
  • 额外资源
  • 后续步骤

假设一个简单的nodejs程序的 Dockerfile如下:

FROM node:20-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "./src/index.js"]

当你运行 docker build 命令来创建新镜像时,Docker 会按指定顺序执行 Dockerfile 中的每条指令,为每个命令创建一个层。对于每条指令,Docker 会检查是否可以重用之前构建中的指令。如果发现之前已经执行过类似的指令,Docker 就不需要重新执行,而是使用缓存的结果。这样,你的构建过程会变得更快、更高效,节省宝贵的时间和资源。

有效使用构建缓存可以通过重用之前构建的结果并跳过不必要的工作来实现更快的构建。为了最大化缓存的使用并避免资源密集型和耗时的重建,理解缓存失效的工作原理非常重要。以下是一些可能导致缓存失效的情况:

  • RUN 指令的任何更改 会使该层失效。如果 Dockerfile 中的 RUN 命令有任何修改,Docker 会检测到变化并使构建缓存失效。
  • 使用 COPYADD 指令复制到镜像中的文件的任何更改Docker 会监视项目目录中的任何更改,无论是内容的变化还是属性(如权限)的变化,Docker 都会将这些修改视为触发缓存失效的原因。
  • 一旦某一层失效,所有后续层也会失效。如果由于更改导致任何之前的层(包括基础镜像或中间层)失效,Docker 会确保依赖于它的后续层也失效。这保持了构建过程的同步,防止不一致。

在编写或编辑 Dockerfile 时,注意避免不必要的缓存失效,以确保构建尽可能快速和高效地进行。

实践

在本指南中,你将学习如何有效使用 Docker 构建缓存来优化 Node.js 应用程序的构建过程。

构建应用程序

下载并安装 Docker Desktop

打开终端并克隆这个示例应用程序:

git clone https://github.com/dockersamples/todo-list-app

进入 todo-list-app 目录:

cd todo-list-app

在这个目录中,你会找到名为 Dockerfile 的文件,内容如下:

FROM node:20-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
EXPOSE 3000
CMD ["node", "./src/index.js"]

执行以下命令来构建 Docker 镜像:

docker build .

构建过程如下所示:

[+] Building 20.0s (10/10) FINISHED

第一行表示整个构建过程花费了 20.0 秒。第一次构建可能会花费一些时间,因为需要安装依赖项。

不做任何更改进行重建

现在,在不更改源代码或 Dockerfile 的情况下重新运行 docker build 命令:

docker build .

后续构建由于缓存机制而变得更快,只要命令和上下文保持不变。Docker 会缓存构建过程中生成的中间层。当你在不更改 Dockerfile 或源代码的情况下重新构建镜像时,Docker 可以重用缓存的层,从而显著加快构建过程。

[+] Building 1.0s (9/9) FINISHED

后续构建仅在 1.0 秒内完成,通过利用缓存层,无需重复耗时的步骤,如安装依赖项。

步骤描述第一次运行时间第二次运行时间
1Dockerfile 加载构建定义0.0 秒0.0 秒
2加载 docker.io/library/node:20-alpine 的元数据2.7 秒0.9 秒
3加载 .dockerignore0.0 秒0.0 秒
4加载构建上下文 (上下文大小: 4.60MB)0.1 秒0.0 秒
5设置工作目录 (WORKDIR)0.1 秒0.0 秒
6将本地代码复制到容器中0.0 秒0.0 秒
7运行 yarn install --production10.0 秒0.0 秒
8导出层2.2 秒0.0 秒
9导出最终镜像3.0 秒0.0 秒

优化 Dockerfile

为了避免每次构建都重新安装相同的依赖项,可以重新组织 Dockerfile 以保持依赖项缓存的有效性,除非确实需要使其失效。对于基于 Node 的应用程序,依赖项定义在 package.json 文件中。你可以在该文件更改时重新安装依赖项,但如果文件未更改,则使用缓存的依赖项。因此,首先复制 package.json 文件,然后安装依赖项,最后复制其他所有内容。这样,只有在 package.json 文件更改时才需要重新创建 yarn 依赖项。

更新 Dockerfile 以首先复制 package.json 文件,安装依赖项,然后复制其他所有内容:

FROM node:20-alpine
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --production 
COPY . . 
EXPOSE 3000
CMD ["node", "src/index.js"]

在与 Dockerfile 相同的文件夹中创建一个名为 .dockerignore 的文件,内容如下:

node_modules

构建新镜像:

docker build .

输出如下:

[+] Building 16.1s (10/10) FINISHED
=> [internal] load build definition from Dockerfile                                               0.0s
=> => transferring dockerfile: 175B                                                               0.0s
=> [internal] load .dockerignore                                                                  0.0s
=> => transferring context: 2B                                                                    0.0s
=> [internal] load metadata for docker.io/library/node:21-alpine                                  0.0s
=> [internal] load build context                                                                  0.8s
=> => transferring context: 53.37MB                                                               0.8s
=> [1/5] FROM docker.io/library/node:21-alpine                                                    0.0s
=> CACHED [2/5] WORKDIR /app                                                                      0.0s
=> [3/5] COPY package.json yarn.lock ./                                                           0.2s
=> [4/5] RUN yarn install --production                                                           14.0s
=> [5/5] COPY . .                                                                                 0.5s
=> exporting to image                                                                             0.6s
=> => exporting layers                                                                            0.6s
=> => writing image     
sha256:d6f819013566c54c50124ed94d5e66c452325327217f4f04399b45f94e37d25        0.0s
=> => naming to docker.io/library/node-app:2.0                                                 0.0s

现在,修改 src/static/index.html 文件(例如将标题更改为 “The Awesome Todo App”)。

构建 Docker 镜像。此时,你的输出应有所不同:

docker build -t node-app:3.0 .

输出如下:

[+] Building 1.2s (10/10) FINISHED 
=> [internal] load build definition from Dockerfile                                               0.0s
=> => transferring dockerfile: 37B                                                                0.0s
=> [internal] load .dockerignore                                                                  0.0s
=> => transferring context: 2B                                                                    0.0s
=> [internal] load metadata for docker.io/library/node:21-alpine                                  0.0s 
=> [internal] load build context                                                                  0.2s
=> => transferring context: 450.43kB                                                              0.2s
=> [1/5] FROM docker.io/library/node:21-alpine                                                    0.0s
=> CACHED [2/5] WORKDIR /app                                                                      0.0s
=> CACHED [3/5] COPY package.json yarn.lock ./                                                    0.0s
=> CACHED [4/5] RUN yarninstall --production                                                     0.0s
=> [5/5] COPY . .                                                                                 0.5s 
=> exporting to image                                                                             0.3s
=> => exporting layers                                                                            0.3s
=> => writing image     
sha256:91790c87bcb096a83c2bd4eb512bc8b134c757cda0bdee4038187f98148e2eda       0.0s
=> => naming to docker.io/library/node-app:3.0                                                 0.0s

首先,你会注意到构建速度快了很多。你会看到多个步骤使用了之前缓存的层。这是个好消息;你正在使用构建缓存。推送和拉取此镜像及其更新也会快得多。

通过遵循这些优化技术,你可以加快 Docker 构建速度,提高开发效率,缩短迭代周期,提高开发生产力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/32840.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Pnpm:包管理的新星,如何颠覆 Npm 和 Yarn

在探索现代 JavaScript 生态系统时,我们常常会遇到新兴技术的快速迭代和改进。其中,包管理工具的发展尤为重要,因为它们直接影响开发效率和项目性能。最近,pnpm 作为一种新的包管理工具引起了广泛关注。它不仅挑战了传统工具如 np…

vue3路由的使用

1、引用路由组件 npm install vue-router 2、创建路由 根据项目结构创建对应的组件(home\news\about) 在 src 目录下创建 router/index.ts //引入路由 import { createRouter,createWebHistory,createWebHashHistory } from vue-router import Home …

總結光學(完)

參考: 陈曦<<光学讲义>>http://ithatron.phys.tsinghua.edu.cn/downloads/optics.pdf 1 波动光学 最简单的一种波是平面波。........... 一个波的波前是指相位相同的点构成的面。波的传播方向垂直于波面。 我们在此将讨论的光波特指波长远大于原子尺度又远小于…

关于Pytorch转换为MindSpore的一点建议

一、事先准备 必须要对Mindspore有一些了解&#xff0c;因为这个框架确实有些和其它流程不一样的地方&#xff0c;比如算子计算、训练过程中的自动微分&#xff0c;所以这两个课程要好好过一遍&#xff0c;官网介绍文档最好也要过一遍 1、零基础Mindspore&#xff1a;https://…

学生作业管理系统设计文档

一、项目概述 本系统设计文档旨在为学生作业管理系统提供一个全面的设计方案。该系统旨在提高作业管理的效率&#xff0c;减轻教师的工作负担&#xff0c;并为学生提供一个清晰、便捷的作业提交和查看平台。系统需具备作业发布、作业提交、作业批改、成绩查看等基本功能&#…

linux服务器运行pycharm代码

一、pycharm代码上传服务器 1、进行配置 2、建立ssh连接&#xff08;选择文件传输协议SFTP&#xff09; 3、设置服务器名&#xff08;自定义&#xff09; 4、点击SSH配置右侧的"…"&#xff0c;进行SSH内容设置&#xff1a; 5、输入服务器信息 6、进行本地项目与远程…

AIGC系列之一-一文理解什么是Embedding嵌入技术

摘要&#xff1a;嵌入技术&#xff08;Embedding&#xff09;是一种将高维数据映射到低维空间的技术&#xff0c;在人工智能与图形学研究中被广泛应用。本文将介绍嵌入技术的基本概念、原理以及在 AIGC&#xff08;Artificial Intelligence and Graphics Computing&#xff09;…

基于STM32的智能农业灌溉系统

目录 引言环境准备智能农业灌溉系统基础代码实现&#xff1a;实现智能农业灌溉系统 4.1 数据采集模块4.2 数据处理与分析4.3 控制系统实现4.4 用户界面与数据可视化应用场景&#xff1a;智能农业管理与优化问题解决方案与优化收尾与总结 1. 引言 智能农业灌溉系统通过使用ST…

FPGA学习网站推荐

FPGA学习网站推荐 本文首发于公众号&#xff1a;FPGA开源工坊 引言 FPGA的学习主要分为以下两部分 语法领域内知识 做FPGA开发肯定要首先去学习相应的编程语言&#xff0c;FPGA开发目前在国内采用最多的就是使用Verilog做开发&#xff0c;其次还有一些遗留下来的项目会采用…

智慧校园综合门户有哪些特点?

智慧校园的门户系统&#xff0c;作为整个智慧校园架构的门户窗口&#xff0c;扮演着至关重要的角色。它如同一座桥梁&#xff0c;将校园内的各种信息资源、应用服务以及管理功能紧密相连&#xff0c;为师生、家长及管理人员提供了一个集中访问的便捷通道。智慧校园门户的设计理…

TDengine 签约红有软件,加速油田信息化进程

在数字化浪潮席卷全球的今天&#xff0c;油田信息化建设已成为提升油气生产效率和管理水平的重要途径。作为中国油田信息化领域的领军企业&#xff0c;红有软件股份有限公司通过其自主研发的信息化基础开发平台&#xff0c;已经成功助力多个油气田项目实现数字化转型&#xff0…

【Java】Java基础语法

一、注释详解 1.1 注释的语法&#xff1a; // 单行注释/*多行注释 *//**文档注释 */ 1.2 注释的特点&#xff1a; 注释不影响程序的执行&#xff0c;在Javac命令进行编译后会将注释去掉 1.3 注释的快捷键 二、字面量详解 2.1 字面量的概念&#xff1a; 计算机是用来处理…

DS:二叉树的链式存储及遍历

​ 欢迎来到Harper.Lee的学习世界&#xff01; 博主主页传送门&#xff1a;Harper.Lee的博客主页 想要一起进步的uu可以来后台找我哦&#xff01; ​ 一、引入 1.1 二叉树的存储方式 在之前接触到的满二叉树和完全二叉树使用的是数组的存储方式&#xff08;DS&#xff1a;树与…

thrift接口调用工具

写了一个thrift接口调用工具 导入thrift文件就可以直接调用相应接口 工具会根据thrift文件中接口的参数名&#xff0c;参数类型&#xff0c;返回值等等&#xff0c;自动生成接口参数&#xff0c;和结果json化显示。 https://github.com/HuaGouFdog/Fdog-Kit

RabbitMQ 关闭、开启消费

默认情况下&#xff0c;消费者在项目启动的时候就开始监听队列消费了&#xff0c;在某些特殊情况&#xff0c;可能需要临时关闭消费 Autowiredprivate RabbitTemplate rabbitTemplate;/*** 发送消息** author 蔡定努*/GetMappingpublic boolean aa() {rabbitTemplate.convertSe…

UnityShader参数语法总结

[Space()] 作用&#xff1a;在Inspector面板中的字段或字段组之间增加垂直空间。 数值参数&#xff1a;[Space()]中的参数指定了要添加的像素单位&#xff08;或Unity的GUI单位&#xff09;的空间量。如果不指定数值&#xff0c;默认是8个像素。 放置位置&#xff1a;它直接放置…

深入了解软件设计模式:创新应用与优化代码结构

前言 在软件开发中&#xff0c;设计模式被广泛应用&#xff0c;通常分为三大类&#xff1a;创建型、结构型和行为型。这些模式经过时间验证&#xff0c;在解决特定问题和优化代码结构方面发挥了重要作用。本文将详细介绍每一类设计模式&#xff0c;并通过具体实例展示它们的应…

实际项目开发:Spring集成Redis,并实现短信登录功能

redis新手&#xff0c;学了几种基本数据类型&#xff0c;却不知道怎么使用&#xff1f; 总是一边学一边忘&#xff1f; 学会了Redis的大多数使用命令&#xff0c;却不知道如何在项目中使用&#xff1f; 本文将从实际出发&#xff0c;为大家解决这些问题。 我是蚊子码农&#xf…

折线统计图 初级

此为折线统计图的初级题目。 本次的题目较难&#xff0c;菜鸡请退出。 4. 下图显示了甲、乙两台电脑的价格以及它们已使用的年数&#xff0c;从图中可以知道( )。 15. 妈妈去菜市场买菜&#xff0c;走到半路遇到一位熟人聊了一会儿&#xff0c;突然发现忘了带钱。于是马上回…