当前位置: 首页 > news >正文

使用构建缓存优化 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 构建速度,提高开发效率,缩短迭代周期,提高开发生产力。

相关文章:

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

使用构建缓存优化 Docker 镜像构建 目录 实践构建应用程序额外资源后续步骤 假设一个简单的nodejs程序的 Dockerfile如下: FROM node:20-alpine WORKDIR /app COPY . . RUN yarn install --production CMD ["node", "./src/index.js"]当你运…...

微软搁置水下数据中心项目——项目纳蒂克相比陆地服务器故障更少

“我的团队努力了,并且成功了,”COI负责人诺埃尔沃尔什说。 微软已悄然终止了始于2013年的水下数据中心(UDC)项目“纳蒂克”。该公司向DatacenterDynamics确认了这一消息,微软云运营与创新部门负责人诺埃尔沃尔什表示…...

国产AI算力训练大模型技术实践

ChatGPT引领AI大模型热潮,国内外模型如雨后春笋,掀起新一轮科技浪潮。然而,国内大模型研发推广亦面临不小挑战。面对机遇与挑战,我们需保持清醒,持续推进技术创新与应用落地。 为应对挑战,我们需从战略高度…...

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

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

C#中File类常见用法总结

前言 我们在开发C#软件的过程中,经常需要和文件打交道,那么File类在C#中是我们使用非常频繁的一个类,本文就是详细介绍File类在C#中的常见用法。 1、判断文件是否存在 string fileName "1.txt";bool isExist File.Exists(fileN…...

CesiumJS【Basic】- #007 绘制直线段以避免地球曲率的影响

文章目录 绘制直线段以避免地球曲率的影响1 目标2 实现绘制直线段以避免地球曲率的影响 1 目标 绘制直线段以避免地球曲率的影响 2 实现 在CesiumJS中,直线的弯曲是由地球曲率引起的,因为地球是一个球体而不是一个平面。因此,如果您要在地球上绘制两点之间的直线,它将会…...

解决文件或文件夹无法删除问题

最近呢,发现很多小伙伴都会遇到一个问题,就是当我要删掉一个文件或者软件的时候,就会弹出[操作无法完成,因为其中的文件夹或文件已在另一个程序中打开] 然后我就翻看网站,很多都是什么去**[任务管理器]修改[资源管理器…...

【报错】JDBC SQL语句表名报错 解决办法

解决办法 修改检测等级 不是检测有问题吗,那就将idea的检测问题取消掉或者修改检测问题等级,根本问题上我们写的sql语句是一个字符串传过去,只要在mysql查询语句能够正确执行,不要这种检测也罢。...

【Nvidia+AI摄像头】面向机器人双目视觉相机

随着人工智能和机器人技术的不断发展,双目深度相机作为一种重要的传感器,正在被广泛应用于各种机器人系统中。双目深度相机作为机器人不可或缺的感知器件,其高精度深度信息为机器人提供环境感知、立体视觉、姿态识别等功能,让机器…...

Hive数据锁问题处理

在测试环境有定时任务会定期将flume采集的数据load到hive表中,在查看yarn application过程中发现load操作没有执行,且后续的任务在上一个任务执行结束后很久才开始。感觉像是阻塞一样,于是手动执行相关脚本,发现也是会卡住&#x…...

使用VisualBox+Vagrant搭建Centos虚拟机环境

1.下载并安装VisualBox; 2.下载并安装Vagrant; 3.打开cmd窗口,执行命令vagrant init centos/7,初始化centos环境,该步骤受网络带宽影响,可能挂级30分钟到1个小时; 4.启动虚拟机:vagrant up&…...

PHP框架之Yii框架

Yii框架详细说明 Yii框架是一个基于组件的高性能PHP框架,用于开发大型Web应用。Yii框架由薛强创立,自2008年1月1日开始开发,至今已成为PHP开发领域的佼佼者之一。Yii框架以其高效、安全、灵活和可扩展的特性,赢得了众多开发者的青…...

数组元素去重

1 .旧数组不重复的元素放到新数组 2 .遍历旧数组,拿旧数组查新数组,如果元素在新数组内没有出现过就添加 3 .利用 新数组.indexOf(数组元素) 如果返回-1就说明新数组里没有该元素 //封装一个 去重的函数 function unique(arr) {var newArr[];for(var …...

Redis 的安装与部署

本文为Redis的Linux版单机部署。 上传 redis-3.2.8 源码到 /opt/software/ 解压到 /opt/module/ [huweihadoop101 software]$ tar -zxvf redis-3.2.8.tar.gz -C /opt/module/安装依赖 [huweihadoop101 software]$ sudo yum -y install gcc-c tclRedis是C语言编写的 编译安装…...

Applied Spatial Statistics(七):Python 中的空间回归

Applied Spatial Statistics(七):Python 中的空间回归 本笔记本演示了如何使用 pysal 的 spreg 库拟合空间滞后模型和空间误差模型。 OLS空间误差模型空间滞后模型三种模型的比较探索滞后模型中的直接和间接影响 import numpy as np impor…...

如何关闭软件开机自启,提升电脑开机速度?

如何关闭软件开机自启,提升电脑开机速度?大家知道,很多软件在安装时默认都会设置为开机自动启动。但是,有很多软件在我们开机之后并不是马上需要用到的,开机启动的软件过多会导致电脑开机变慢。那么,如何关…...

如何培养员工的竞争意识

一、背景 在当今快速变化的商业环境中,培养员工的竞争意识对于企业的长期成功至关重要。通过激发员工的竞争精神,企业能够提升整体绩效,增强创新能力,并在市场竞争中保持领先地位。本文将从多个方面探讨如何培养员工的竞争意识。 二、明确目标设定 设定清晰具体的目标:明…...

2025秋招NLP算法面试真题(二)-史上最全Transformer面试题:灵魂20问帮你彻底搞定Transformer

简单介绍 之前的20个问题的文章在这里: https://zhuanlan.zhihu.com/p/148656446 其实这20个问题不是让大家背答案,而是为了帮助大家梳理 transformer的相关知识点,所以你注意看会发现我的问题也是有某种顺序的。 本文涉及到的代码可以在…...

redis初步认识(一)

文章目录 概述安装编译 string数据结构基础命令应用对象存储累加器 list结构基础命令应用栈(先进后出FILO)队列 HASH基础命令存储结构应用存储对象 小结 概述 redis 是一个远程字典服务;当然,redis是内存数据库,kv数据库,最基础的…...

Android 开发必备知识点及面试题汇总(Android+Java+算法+性能优化+四大组件……

**虚引用:**顾名思义,就是形同虚设,如果一个对象仅持有虚引用,那么它相当于没有引用,在任何时候都可能被垃圾回收器回收。 7.介绍垃圾回收机制 **标记回收法:**遍历对象图并且记录可到达的对象&#xff0c…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

腾讯云V3签名

想要接入腾讯云的Api&#xff0c;必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口&#xff0c;但总是卡在签名这一步&#xff0c;最后放弃选择SDK&#xff0c;这次终于自己代码实现。 可能腾讯云翻新了接口文档&#xff0c;现在阅读起来&#xff0c;清晰了很多&…...