前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Docker 镜像优化:减小镜像尺寸 原

Docker 镜像优化:减小镜像尺寸 原

作者头像
拓荒者
发布2019-03-11 11:08:41
3.1K0
发布2019-03-11 11:08:41
举报
文章被收录于专栏:运维经验分享运维经验分享

引 言  随着我们对Docker 应用的持续使用,如果不加注意,那么镜像的尺寸就会变得越来越大。很多人在使用Docker 时会发现,团队定制化的Docker 镜像尺寸都至少有1GB 大。镜像越大就意味着编译和部署Docker 应用的时间会越长。因此,我们需要减小需要部署的镜像的尺寸。它会抵消使用Docker 带来的好处,失去快速迭代开发和部署应用的能力。  本文节将深入讨论Docker 镜像层的技术细节以及它们是如何影响最终镜像的大小的。  接下来,我们将在研究Docker 镜像工作原理的过程中,学习如何优化这些镜像层。

链 式 指 令  Docker 镜像尺寸变大的一个原因是很多对编译或运行无关的指令被引入到镜像中。一个常见的案例是打包元数据和缓存。在安装完编译和运行相关的依赖包之后,这些下载的文件就没有存在的必要了。类似clean 的指令可以在很多仓库(如Docker Hub)的Dockerfile 中发现,它们用于清理这类文件,例如: 

图片描述
图片描述

但是,一个Docker 镜像的尺寸是每一个独立镜像层的尺寸之和,这也就是联合文件系统的工作机制。因此,clean 步骤并没有真正删掉相应的硬盘空间,可通过如下命令来查看: 

图片描述
图片描述

记录显示,这里并不存在“负”的镜像层尺寸。于是,Dockerfile 中每一个指令要么保持镜像尺寸不变,要么增加它的尺寸。同时,每一步还会引入新的元数据信息,使得整体尺寸在增大。  为了降低整个镜像的尺寸,清除操作应该在同一镜像层中执行。于是,解决方案是将先前的多条指令合并成一条。当Docker 使用/bin/sh 来执行每一条指令时,我们可以使用Bourne shell 提供的&&操作符来实现链接,例如: 

图片描述
图片描述

现在每一个独立层的尺寸已经足够小了。由于独立镜像层的尺寸被减小,于是整个镜像的尺寸也随之减小。让我们来确认一下它们的尺寸,操作如下: 

图片描述
图片描述
图片描述
图片描述

分离编译镜像和部署镜像  Docker 镜像中另一类无用文件是编译过程中的依赖文件,例如在编译应用程序过程中所依赖的源代码库,如编译文件和头文件。一旦应用程序编译完毕,这些文件就不再有用,因为运行该应用仅需要相关的依赖库。  例如,编译下面这个应用程序,它已经开发完毕并准备部署到Docker 云主机上。这是一个简单的Web 应用程序,采用Go 语言开发,代码树如下图所示。 

图片描述
图片描述

hello.go 的内容如下: 

图片描述
图片描述
图片描述
图片描述

相应的Dockerfile 中记录了如何编译源代码和运行编译结果,内容如下: 

图片描述
图片描述

接下来,我们将展示这个Docker 镜像的尺寸是如何变大的,操作如下所示。  1.首先,编译这个Docker 镜像并记录它的尺寸,操作如下: 

图片描述
图片描述

2.然后,对比运行时实际应用程序的尺寸,操作如下: 

图片描述
图片描述

用Go 语言编写应用程序以及编译代码的一个优势是,它可以生成一个单一可执行文件,这对部署非常方便。Docker 镜像中除去该可执行文件占据的空间,全都是Docker 基础镜像引入的无用文件。可以发现,来自基础镜像的文件使得整个镜像尺寸增加了将近100倍。  同样,我们可以优化这个最终的Docker 镜像并仅打包最后的hello 可执行文件和相关的依赖包,然后部署到生产环境。优化步骤如下所示。  1.首先,复制运行容器中的可执行文件到Docker 宿主机,操作如下: 

图片描述
图片描述

2.如果前面的依赖库是一个静态库,那这一步就已经完成了,直接进入下一步。但是,Go 工具编译时默认采用共享库机制,为了让二进制文件直接运行,还需要这些共享库,操作如下: 

图片描述
图片描述

3.接下来,保存全部共享库到Docker 宿主机,采用docker cp –L 命令,操作如下: 

图片描述
图片描述

4.创建一个新的Dockerfile 用于编译这个只有二进制(binary-only)的镜像。注意,如何使用ADD 指令将共享库添加到Docker 镜像中,操作如下: 

图片描述
图片描述

5.现在,所有必要的文件都在这个“binary-only”的镜像中,文件夹中的目录结构树如下图所示。 

图片描述
图片描述

6.最后,采用build/Dockerfile 文件编译这个用于部署的二进制Docker 镜像,最终生成的镜像将比原来的小,操作如下: 

图片描述
图片描述

同样的方法可以用于编译其他应用,例如通常采用./configure && make && makeinstall 方式安装的那些软件。同样,可以用于那些解释性编程语言的应用程序,如Python、Ruby 或者PHP。但是,创建一个“运行时”的Ruby 语言的Docker 镜像还需要进行一些额外处理。这种优化技术的最佳实践案例是在一个可持续开发流程中的应用程序的场景,并且它由于镜像太大导致传输时间太长。  相关图书 

图片描述
图片描述

《高性能Docker》  DockOne社区倾情翻译  阅读本书将掌握Docker性能优化实践  更快、更高效地部署容器,改善开发工作流  【美】艾伦·埃斯皮诺萨 著  陈杰 杨峰 夏彬 译  2016年9月出版  ◎ 帮助读者改善其Docker 工作流,并保证应用在生产环境中顺利进行  ◎ 除了Docker 的基础知识外,还会学到如何优化Docker基础架构和大规模应用

(adsbygoogle = window.adsbygoogle || []).push({});

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018/08/29 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器镜像服务
容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档