07 - 镜像管理之:镜像优化

1 为什么要做镜像优化?


1)随着我们对docker镜像的持续使用,在此过程中如果不加以注意并且优化,镜像的体积会越来越大,很多时候我们在使用docker部署应用时,会发现镜像的体积可能都会在1G以上。

2)镜像体积的增大,不单单会增加磁盘资源与网络资源的开销,也会影响应用的部署效率,使得应用的部署时间会越来越长。



因此,我们需要尽量减小镜像的体积,以加快部署效率、降低资源的开销,而对于镜像的优化,可以通过对dockerfile的优化来实现。


镜像的优化过程:

  • 循序渐进
  • 选择最精简的基础镜像
  • 减少镜像的层数
  • 清理镜像构建的中间产物
  • 注意优化网络请求 尽量去用构建缓存
  • 使用多阶段构建镜像

2 构建镜像的几个原则


2.1 镜像最小化原则

1)选择最精简的基础镜像。

选择体积最小的基础镜像可有效降低镜像体积。如:alpine、busybox等


2)清理镜像构建的中间产物

构建镜像的过程中,当dockerfile的指令执行完成后,删除镜像不需要用的的文件。比如,使用yum安装组件,最后可使用yum clean all镜像清理不需要的文件,或者使用系统rm命令删除不需要的源文件等。


3)减少镜像的层数

镜像是一个分层存储的文件,dockerfile中的每一条指令都会生成一个层,并且镜像对层数也是有一定数量的限制,当前镜像的层数最高是127层,如果不多加注意,将会导致镜像越来越臃肿。因此,可以通过合并dockerfile中可合并的指令,减少最终生成镜像的层数。
例如:在dockerfile中使用RUN执行shell命令的时候,可以用 " && " 将多条命令连接起来。


2.2 构建速度最快化原则

1)充分利用镜像构建缓存

我们可以利用构建的缓存来加快镜像构建速度,Docker构建默认会开启缓存,缓存生效有三个关键点:

  • 镜像父层没有发生变化
  • 构建指令不变
  • 添加文件校验和一致

只要一个构建指令满足这三个条件,这一层镜像构建就不会再执行,它会直接利用之前构建的结果。


但是,如果某一层的镜像缓存失效之后,它之后的镜像层缓存都会失效。因此,我们应该把变化最少的部分放在Dockerfile的前面,这样可以充分利用镜像缓存;dockerfile中有可能导致缓存失效的命令WORKDIR、CMD、ENV、ADD等,像这些命令最好放到dockerfile文件的底部,以便在构建镜像过程中最大限度使用缓存。


2)删除构建目录中(默认:Dockerfile所在目录)不需要用的的文件

编写 .dockerignore 文件过滤构建过程中不必要的文件,或者创建单独的目录,并且目录中仅存在镜像构建过程中需要使用的文件。

要知道:
Docker 在运行时分为 Docker 引擎(也就是服务端守护进程)和客户端工具。Docker 的引擎提供了一组 REST API,被称为 Docker Remote API,而如 docker 命令这样的客户端工具,则是通过这组 API 与 Docker 引擎交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种 docker 功能,但实际上,一切都是使用的远程调用形式在服务端(Docker 引擎)完成。


也就是说,docker build 命令构建镜像,其实并非在本地构建,而是在服务端,也就是 Docker 引擎中构建的。构建镜像时,Docker需要先准备context ,将所有需要的文件收集到进程中。默认的context包含Dockerfile文件所在目录下的所有文件。如果,目录中存在大量不相关的文件,那么就会导致构建缓慢。(换句话说,docker build 默认在构建的时候,会把当前目录下的所有数据发送到docker引擎,因此会导致构建时间变长;但默认不会把当前文件夹的内容都打进镜像,也就是不会导致镜像体积变大

.dockerignore示例如下:
比如在一个构建项目中,我们并不需要.env目录等内容。可以在.dockerignore文件中加入以下内容:
.env/
其实,.dockerignore 的作用和语法类似于 .gitignore,可以忽略一些不需要的文件,这样可以有效加快镜像构建时间。


2.3 注意优化网络请求

我们使用一些镜像源,或者在dockerfile中使用互联网上的url时,去用一些网络比较好的开源站点,这样可以节约时间、减少失败率。


3 dockerfile指令优化

点击这里,查看本节内容。


4 多阶段构建镜像

多阶段构建是一个新特性,需要 Docker 17.05 或更高版本的守护进程和客户端。对于优化 Dockerfiles 并使其易于阅读和维护来说,多阶段构建非常有用。


4.1 使用多阶段构建

对于多阶段构建,可以在 Dockerfile 中使用多个 FROM 语句。每个 FROM 指令都可以使用不同的基础镜像,并且它们都开始了构建的新阶段。你可以选择性地将工件从一个阶段复制到另一个阶段,并舍弃在最终镜像中您不想要的所有内容。


如下Dockerfile:
FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]  

最后面的 --from=0​​ 参数,是指从前边的阶段中拷贝文件到当前阶段中(没有拷贝的东西默认都会被舍弃),Dockerfile中包含多个FROM语句时,0 代表第一个阶段。除了使用数字,我们还可以给阶段命名。


和以往一样运行 docker build即可:
$ docker build -t alexellis2/href-counter:latest .

思考下:它是如何工作的?
第二个 FROM 指令用 alpine:latest 镜像作为基础镜像,开始一个新的构建阶段。COPY --from=0 行,只将前一阶段的构建工件复制到这个新阶段。第一阶段中的Go SDK 和任何中间工件都会被抛弃,不会保存到最终的镜像中。


4.2 为构建阶段命名

默认情况下,如果我们没有对阶段进行命名,那么可以通过它们的整数来引用它们(比如通过 --from=0 来引用第一个阶段),FROM 指令的第一个整数从 0 开始。另外,你可以通过添加一个 AS < NAME > 到 FROM 指令来给该阶段进行命名。下面示例通过命名阶段并在 COPY 指令中使用名称改进了前面一个示例。这意味着,即使 Dockerfile 中的各阶段被重新排序,COPY 也不会破坏。


改进后的Dockerfile:

FROM golang:1.7.3 AS builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go    .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]  

4.3 在特定的构建阶段停止

在构建映像时,不必构建包括每个阶段的整个 Dockerfile。你可以指定目标构建阶段。以下命令假设你正在使用之前的 Dockerfile,但是在名为 builder 的阶段停止:

docker build --target builder -t alexellis2/href-counter:latest .

这可能非常强有力的几个场景是:

  • 调试一个特定的构建阶段;
  • 使用一个测试(testing)阶段,在这个阶段你的应用会被测试数据填充,但是在构建产品时,使用真实数据。

4.4 使用外部镜像作为“阶段”

当使用多阶段构建时,您不受限于从 Dockerfile 中先前创建的阶段进行复制。您可以使用 COPY --from 指令从单独的镜像中进行复制,可以使用本地镜像名称、本地或 Docker 注册表上可用的标签或标签 ID。Docker 客户端会在必要时拉取镜像并从中复制工件。语法是:

COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf

4.5 把以前的阶段作为新的阶段

在使用 FROM 指令时,您可以引用前一阶段的内容。例如:

FROM alpine:latest as builder
RUN apk --no-cache add build-baseFROM builder as build1
COPY source1.cpp source.cpp
RUN g++ -o /binary source.cpp

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

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

相关文章

08 视图

视图 视图概念 视图是存储的查询语句,当调用的时候,产生结果集,视图充当的是虚拟表的角色。其实视图可以理解为一个表或多个表中导出来的表&#xff0c;作用和真实表一样&#xff0c;包含一系列带有行和列的数据 视图中&#xff0c;用户可以使用SELECT语句查询数据&#xff0…

Fabric V2.5 通用溯源系统——应用前端部分设计及简易二次开发

本节对Fabric V2.5 通用溯源系统的前端部分做一个简单的介绍。包括目录结构、文件作用简述、用户注册登录实现、农产品信息上链溯源实现的介绍。同时提供了简易二次开发的教程(面向需要在短时间内二次开发),将本项目修改为商品溯源项目,仅修改前端部分。本节内容需要订阅《…

Python报错ModuleNotFoundError: No module named ‘numpy‘

原因&#xff1a;缺少“numpy” 进入python安装路径&#xff0c;script路径内 在路径下启动终端 01.更新numpy python -m pip install --upgrade pip 02.安装 pip install numpy 03.运行python python 04.导入包 from numpy import * 问题已解决。

凌鲨客户端架构

客户端架构 客户端使用了tauri作为主框架&#xff0c;通过rust和内置应用(sidecar)为前端界面提供额外能力。 内置应用(sidecar) 应用 相关项目 说明 devc 开发环境容器工具 gitspy 本地git仓库管理工具 grpcutil grpc调用工具 mongo 通讯协议 mongo协议转发工具 …

MATLAB知识点:循环语句的经典练习题:二分搜索

​讲解视频&#xff1a;可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇&#xff08;数学建模清风主讲&#xff0c;适合零基础同学观看&#xff09;_哔哩哔哩_bilibili 节选自​第4章&#xff1a;MATLAB程序流程控制 这个例题我们…

SSD LDPC纠错算法的重要性

固态硬盘&#xff08;Solid State Drives, SSD&#xff09;作为计算机行业中最具革命性的技术之一&#xff0c;凭借其更快的读写速度、增强的耐用性和能效&#xff0c;已经成为大多数用户的首选存储方案。然而&#xff0c;如同任何其他技术一样&#xff0c;SSD也面临自身的挑战…

探索云原生世界:Serverless 技术的崛起与应用

在云原生架构的浪潮中&#xff0c;Serverless 技术正逐渐崭露头角&#xff0c;成为开发者们极具吸引力的选择。Serverless 的出现颠覆了传统的服务器管理模式&#xff0c;为应用开发带来了全新的可能性。 Serverless 架构是一种无需管理服务器的新型架构&#xff0c;它允许开发…

RabbitMQ 基本介绍

RabbitMQ 基本介绍 消息模型 所有 MQ 产品从模型抽象上来说都是一样的过程&#xff1a; 消费者&#xff08;consumer&#xff09;订阅某个队列。生产者&#xff08;producer&#xff09;创建消息&#xff0c;然后发布到队列&#xff08;queue&#xff09;中&#xff0c;最后…

大模型快速实现python3+html内容在线渲染

需求&#xff1a; 有一份数据需要通过前端在线展示给用户&#xff0c;不需要复杂的样式交互&#xff0c;后端服务是基于Python3实现的API接口&#xff0c;对前端技术不是很了解&#xff0c;需要快速实现该需求。类似样式即可&#xff1a; 思路&#xff1a; 如果页面不复杂&am…

【QT】对比C#的ArrayList,qt中也有自己的通用容器(若有误,恳请直接指出)

在Qt中&#xff0c;可以使用QList或QVariantList来代替C#中的ArrayList。QList是Qt中的一个通用容器类&#xff0c;类似于C#中的List<T>&#xff0c;但它不是类型安全的。另一方面&#xff0c;QVariantList是QList<QVariant>的别名&#xff0c;用于存储可以包含任何…

软件测试实战,Web项目网页bug定位详细分析总结(详全)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、前置条件 1&a…

归并排序

参考链接 排序算法&#xff1a;归并排序【图解代码】_哔哩哔哩_bilibili #include <stdio.h> #include <stdlib.h>// 合并 void merge(int arr[], int tempArr[], int left, int mid, int right) {// 标记左半区第一个未排序的元素int l_pos left;// 标记右半区…

中国制造2035任重道远前途光明wordpress外贸独立站模板

生物能源wordpress外贸公司模板 生物能源wordpress外贸公司模板&#xff0c;生物能源、生物化工行业外贸公司网站模板。 https://www.jianzhanpress.com/?p3649 汽车配件wordpress外贸网站模板 汽车配件wordpress外贸网站模板&#xff0c;汽车零配件外贸公司自建站外贸英文…

2023年甘肃省职业院校技能大赛高职组“信息安全管理与评估”(赛项样卷A)

信息安全管理与评估 第一阶段 网络平台搭建与设备安全防护 目 录 第一阶段竞赛项目试题 3 介绍 3 所需的设备、机械、装置和材料 3 评分方案 3 注意事项 3 项目和任务描述 3 1.网络拓扑图 3 2.IP地址规划表 4 工作任务 5 任务1&#xff1a;网络平台搭建 6 任务2&#xff1a;网…

基于单片机的储油罐液位无线监测系统

摘要: 本设计通过无线通信技术为油田储油罐设计了一款液位测量装置,以STC89C52 单片机为中心控制器,采用超声波测距模块HC-SR04 作为液位测量传感器,选用nRF24L01 无线通信模块对采集到的数据进行实时发送与接收,然后将接收到的数据实时处理后传送到上位机进行显示,达到液…

大创项目技术总结(复试准备)

&#xff08;一&#xff09;项目特色 &#xff08;1&#xff09;AI助力阿尔兹海默症的“老药新用”&#xff1a;“老药新用”目前已成为现在的研究趋势。在我们的项目当中我们使用了LDA文本主题模型的机器学习方法来对相关论文文本数据进行文本挖掘&#xff0c;并使用挖掘结果…

安卓部分手机使用webview加载链接后白屏(Android低版本会出现的问题)

前言 大爷&#xff1a;小伙我这手机怎么打开你们呢这个是白屏什么都不显示。 大娘&#xff1a;小伙我这也是打开你们呢这功能&#xff0c;就是一个白屏什么也没有&#xff0c;你们呢的应用不会有病毒吧。 小伙&#xff1a;我的手机也正常&#xff1b; 同事&#xff1a;我的也正…

【数据结构】堆排序

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解堆排序&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 一. 堆的概念二. 堆排序&#xff08;以升序为例&#xff09;三. 代码 一. 堆的概念 如果有一个…

rust入门(1)创建项目

安装 vscode 安装插件 rust-analyzerNative Debug vscode 配置自动格式化代码 settings.json{"editor.defaultFoldingRangeProvider": null,"[rust]": {"editor.defaultFormatter": "rust-lang.rust-analyzer", // Makes the magi…

3. 在Go语言项目中使用Zap日志库

文章目录 一、介绍二、 默认的Go Logger1. 实现Go Logger2. 设置Logger3. 使用Logger4. Logger的运行5. Go Logger的优势和劣势 三、Uber-go Zap1. 为什么选择Uber-go zap2. 安装3. 配置Zap Logger4. 定制logger4.1 将日志写入文件而不是终端4.2 将JSON Encoder更改为普通的Log…