Docker系列之镜像瘦身(五)

本节我们来讲讲在我们在构建镜像过程中不出问题,同时使得最后所构建的镜像文件大小尽可能最小。

640?wx_fmt=gif

缓存(cache)

Docker的优势之一在于提供了缓存,加速镜像迭代构建,我们知道构建镜像使用docker build命令,也就是说通过docker build的缓存机制实现了镜像的复用,不仅节省镜像存储空间,也为镜像构建节省了大量时间。

 

Docker会由上至下逐步执行Dockerfile中的指令,按顺序执行每个指令,在检查每条指令时,Docker在其缓存中查找现有的中间图像,可能会重用而不是创建新的中间图像,如果缓存无效,则使其无效的指令和后续所有Dockerfile指令都会重新生成新的中间镜像。

一旦缓存失效,就可以使用Dockerfile中的其余指令,所以从Dockerfile的顶部开始,如果基础映像(父镜像)已经在缓存中,则重用。

然后继续执行下一条指令与从该基础图像导出的高速缓存中所有子镜像进较,比较每个缓存的中间镜像以查看指令是否找到并缓存是否命中,如果高速缓存未命中,则高速缓存无效,如此重复执行以上过程,最终到达Dockerfile的末尾。

大多数新指令只是与中间镜像中的指令进行比较,如果匹配,则使用缓存副本。比如,当在Dockerfile中执行RUN pip install -r test.txt指令时,Docker会在其本地缓存的中间图像中搜索相同的指令,但是旧的和新的test.txt文件中的内容不会进行比较。如果我们使用新软件包更新test.txt文件并使用RUN pip install指令希望使用新软件包名称重新运行软件包安装,如果是这种情况可能会出现问题。

同时呢,ADD和COPY与其他Docker指令不同,ADD和COPY指令需要Docker查看文件中的内容以确定是否存在缓存命中,Docker将会引用文件内容的校验和与现有中间图像中的校验和进行比较,如果文件内容或元数据已更改,则缓存无效。

 

从如上我们对Dokcer缓存机制的大致讲解,若我们对指令进行了更改,那么该指令的后续每一层可能会经常重建,所以为了更好的利用缓存,我们需要将可能需要更改的指令尽可能的放在比较低的位置。当我们在构建镜像时我们可以指定参数(--no-cache=true)来关闭缓存。当我们需要更新源时,我们通过链式调用apt-get-update和apt-get-install来避免缓存丢失问题。

在Docker中我们可以通过命令来监控文件镜像和容器文件大小,我们知道docker container ls命令查看容器列表,docker container ls -s 则可以查看容器大小,如下:

640?wx_fmt=png

为了查看镜像构建中中间镜像历史记录,使用命令docker image history imagename:tag ,为了更清晰看到镜像中每一层的内容,我们可以使用库https://github.com/wagoodman/dive,比如我们上一节所构建的镜像为webapi。我们安装完dive库后,然后查看镜像中的每一层,通过如下命令。

640?wx_fmt=png

640?wx_fmt=png

640?wx_fmt=gif

文件忽略(.dockerignore)

我们知道Docker有两个组件:客户端和守护进程,当我们编写docker命令时,我们使用客户端向Docker deamon发送命令,该命令执行所有工作,这里我们需要知道客户端和守护进程可以单独部署到两台独立机器上,为了让Docker守护进程使用docker build从Dockerfile文件中构建映像,客户端需要向其发送执行命令的“上下文”, 上下文基本上可以说是传递给docker build命令的目录中的所有文件,使用Dockerfile构建时,我们在客户端可以清楚看到发送的上下文,例如如下:

640?wx_fmt=png

对于大型项目而言,上下文可能会变得非常大,毫无疑问这将会减缓通过Dockerfile构建镜像的速度,因为我们必须等待客户端将所有文件发送到守护进程。比如在ASP.NET Core应用程序中,在项目根目录下可能包含大量文件,这些文件对于大多数Dockerfile构建来说都不是必需的,比如Git文件或者SVN文件,obj、bin等文件, 所有这些附加文件在作为上下文的一部分发送时会减慢构建速度。docker为我们提供了解决方案,我们可以通过在根目录中创建.dockerignore文件来忽略不需要的文件,.dockerignore类似于.gitignore文件,其中包含Docker与文件名匹配的模式列表,并在制作镜像时忽略,比如如下忽略

640?wx_fmt=png

当我们在客户端执行docker build命令来创建映像时,Docker会检查.dockerignore文件,如果存在此文件,它会逐行浏览文件并使用Go的filepath.Match规则以及Docker自身的一些规则来匹配文件名以此来进行忽略。比如在.dockerignore文件中包含* .vs将排除带有.vs扩展名的文件。我们可以使用以#开头的注释来解释在.dockerignore中正在执行的操作。.dockerignore可以帮助减小镜像大小,文件越少意味着镜像越小,镜像越快,减少构建缓存失效,如果日志或其他文件正在更改,并且我们的镜像因其缓存而使其缓存失效,则会降低构建周期。综上我们针对需要使得我们所构建的镜像可以注意以下几方面:

640?wx_fmt=gif

1.使用官方镜像,可能很多文章或博客讲解的镜像已过时。

2.若可能,尽可能使用Alpine镜像,以保持镜像轻量级。

3.如果使用apt,在同一指令中将RUN apt-get update与apt-get install结合使用, 然后在该链式指令中链接多个包, 使用\字符在多行中按字母顺序列出包,最后使用rm -rf /var/lib/apt/lists/* 的目的在于清除apt缓存而不会使其缓存保存到镜像层上。例如:RUN apt-get update && apt-get install -y \package-one \package-two && rm -rf /var/lib/apt/lists/*

4.将可能需要更改的指令尽量放在Dockerfile比较低的位置(可能的话)

5..使用.dockerignore文件将不需要的和不必要的文件留在镜像之外。

6.可以尝试结合使用dive库监控镜像层,然后合理优化镜像大小。

640?wx_fmt=gif

.NET Core使用Docker镜像优化

接下来我们来一起看看针对上一节所写的Dockerfile文件进行分析,看看是否可以为镜像瘦身而进一步优化,上一节的构建镜像文件说明书如下:

640?wx_fmt=png

首先我们获取基础镜像,然后只是复制项目文件而不是复制所有文件,这可以避免额外无关的还原,并允许我们重用中间镜像层,如果我们更改项目文件,只是会再次来一遍重新复制,这也就意味着更快的构建!如果是自包含的应用程序,我们下载对应的镜像而不包含运行时镜像,这样镜像大小最小,同时最后运行时自包含应用程序则无需使用dotnet命令,直接切换到项目根目录通过CMD执行即可。

640?wx_fmt=gif

.NET Core使用Docker移除未使用代码

我们使用预发布的包工具《https://www.nuget.org/packages/Microsoft.Packaging.Tools.Trimming/1.1.0-preview1-25818-01》,通过它我们可以查看应用程序并删除没有调用的代码和二进制文件,接下来我们包括Microsoft.Packaging.Tools.Trimming添加包以及忽略文件基于上一节构建镜像进行如下改造。

640?wx_fmt=png

640?wx_fmt=png

640?wx_fmt=png

640?wx_fmt=png

由如上第一张图我们可以看到,当我们添加了忽略文件后,它将上下文从4.206MB减少到16.9KB,而无需花费更多时间来发送上下文,现在可以说是秒送。 本节我们详细讲解了从哪几方面入手来瘦身镜像,下一节我们深入讲讲Docker中的网络内容,感谢您的阅读,下节再会。 

推荐阅读

(点击标题可跳转阅读)

Docker系列之AspNetCore Runtime VS .NetCore Runtime VS SDK(四)

Docker系列之.NET Core入门(三)

Docker系列之烹饪披萨(二)

Docker系列开篇之Virtual Machine VS Container(一)

640?wx_fmt=png

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

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

相关文章

一张图了解.Net Core和.NetFx和.Net Standard和Xamarin关系

一张图了解.Net Core和.Net Framework和.Net Standard和Xamarin关系总结.NET Standard是一项API规范,每一个特定的版本,都定义了必须实现的基类库。.NET Core是一个托管框架,针对构建控制台、云、ASP.NET Core和UWP应用程序进行了优化。每一种…

Java修炼之路——基础篇——String

String 1:字符串的不可变性 什么是不可变对象?不可变对象是指创建后无法变更的对象 String为什么是不可变的?String类为final,并且内部字符数组也为final。所以String对象是不可变对象。 String类为什么要设计为不可变&#xff1…

VS, VS Code, VS Online, VS xxx, 你都分清了吗?

首先说说部分童鞋容易混淆的 Visual Studio 和 Visual Studio Code 吧。其实,它们俩的关系,就相当于 Java 和 JavaScript,没啥关系。再说说 Visual Studio Online。这就复杂了。历史上,出现过两个 Visual Studio Online&#xff0…

Java修炼之路——基础篇——Java关键字

1:transient 当对象被序列化时,transient阻止其修饰的对象进行序列化;当反序列化时,此对象的值不会被恢复。 2:instanceof 判断引用指向的对象,是不是某个类及其子类的实例对象; class Person …

.NetCore从零开始使用Skywalking分布式追踪系统

将本文从0开始搭建两个webapi项目,使用Skywalking来追踪他们之间的调用关系及响应时间。开发环境为VisualStudio20191:安装Skywalking,可参考:https://www.cnblogs.com/sunyuliang/p/11422576.html,本列中搭建好后的Skywalking服务…

通过Service访问应用 (1)

目录通过Service访问应用 通过Pod IP访问应用 通过ClusterIP Service在集群内部访问 通过Service访问应用通过之前的操作,应用部署完成了,我们的Demo网站已经成功启动了,那么如何访问网站呢?通过Pod IP访问应用我们可以通过Pod IP…

13张PPT带你了解主动式消息队列处理集群

前言偷偷和你们说,我搞了一份内部资料,该内部资料共有13张PPT,据作者透露,该PPT至少花了整整1周时间才编写完成,其内容简洁明了,内容深度足够,易于初学者理解,也给深度开发人员分享了…

.Net Core 三大Redis客户端对比和使用心得

前言稍微复杂一点的互联网项目,技术选型都可能会涉及Redis,.NetCore的生态越发完善,支持.NetCore的Redis客户端越来越多,下面三款常见的Redis客户端,相信大家平时或多或少用到一些,结合平时对三款客户端的使…

队长开卖自家产“翠香”猕猴桃

猕猴桃品种有很多,但不是所有的果子都叫翠香。这两天我在公众号里卖了这个翠香猕猴桃,可能是有同学以为是做广告卖水果,其实是家里的亲戚猕猴桃成熟了,辛苦一年下来地里一共结了3000斤猕猴桃,遇到了一个难题就是如何把…

Java修炼之路——基础篇——Java集合类

集合类的全景图 常用集合类特性 1. Collection:每个位置对应一个元素1.1: List 存放有序元素,允许重复元素,允许元素为null1.1.1: ArrayList:内部结构为数组;初始容量为10;插入、删除的移动速度慢&#x…

小卓.NET中文编程特点介绍

大家好,我在介绍一下我的全新编程语言-卓语言。小卓编程是卓语言的一个开发工具,可以在里面实现绘图、动画、事件响应等等功能。关于中文编程,一直以来都有争议。我针对以往中文编程的缺点而开发了一种全新的编程语言。首先 &…

2019-02-28-算法-进化(盛最多水的容器)

题目描述 给定 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以…

CAP 2.6 版本发布通告

前言今天,我们很高兴宣布 CAP 发布 2.6 版本正式版。同时我们也很高兴的告诉你 CAP 在 GitHub 已经突破了3000 Star.自从上次 CAP 2.5 版本发布 以来,已经过去了几个月的时间,关注的朋友可能知道,在这几个月的时间里,也…

求助:现在有一个可以进体制“养老”的坑,我该不该跳?

对不起,在当下互联网人生活的环境中,并没有可以“养老”的坑。对不起,在当下互联网人生活的环境中,也没有绝对”稳定“的企业。技术人的职业发展,以”适者生存“为核心原则,每一种职业环境都有相应的职业成…

给 asp.net core 写个中间件来记录接口耗时

给 asp.net core 写个中间件来记录接口耗时Intro写接口的难免会遇到别人说接口比较慢,到底慢多少,一个接口服务器处理究竟花了多长时间,如果能有具体的数字来记录每个接口耗时多少,别人再说接口慢的时候看一下接口耗时统计&#x…

Docker(二)-在Docker中部署Nginx实现负载均衡【完整教程】

一、前言【查看完整视频教程(免费),请拉直文尾】在前面的文章中我们已经介绍了如何在Centos7系统中安装Docker以及利用Docker进行Asp.Net Core应用的部署。在本文中,我们将继续介绍利用Docker部署Nginx服务实现负载均衡。文章最后…

设置ABP默认使用中文

ABP提供的启动模板, 默认使用是英文:虽然可以通过右上角的菜单切换成中文, 但是对于国内项目来说, 默认使用中文是很正常的需求.前期准备使用ABP CLI创建一个名为AbpStudy的ASP.NET MVC项目:abp new AbpStudy关于MVC的启动模板可以看文档, 这里就不赘述.使用ABP版本的是当前最新…

基础篇--Java IO--概览

字符流、字节流、输入流、输出流 Java 中使用IO(输入输出)来读取和写入,读写磁盘文件、内存、网络数据。输入输出是相对内存而言,往内存中读数据就为输入流,从内存中往外写就是输出流。 根据处理类型分为字符流、字节…

.NET轻松写博客园爬虫

爬虫,是一种按照一定的规则,自动地抓取网站的程序或者脚本。.NET写爬虫非常简单,并能轻松优化性能。今天我将分享一段简短的代码,爬出博客园前200页精华内容,然后通过微小的改动,将代码升级为多线程爬虫&am…

kettle同步数据中文乱码问题解决

最近在使用kettle进行数据同步的时候,发现同步来的中文数据产生了乱码。试了下网上的解决方案,最终解决了这个问题。步骤如下: 1:kettle中配置源数据库、目标数据库编码 2:编辑“表输入”,去掉勾选“允许建…