虽然Dockerfile简化了镜像构建的过程,并且让这个过程可以进行版本控制,但是很多人在构建镜像中台的时候,会有种把可能用到的东西都打包到镜像中的冲动。这种对Dockerfile的不当使用也会导致很多问题:docker镜像太大。如果你经常使用镜像或者构建镜像,肯定会遇到这么大的镜像,甚至一些能达到2G以上的docker镜像构建起来时间过长。每次构建都需要很长时间,这对于需要经常构建图像的地方(例如单元测试)来说可能是个大问题。多个镜像构建之间的大部分内容是完全一样的,重复的,但是每次都需要做,很浪费时间和资源。希望读者能够对dockerimages有一定的了解。阅读本文至少需要一些前提知识:了解docker的基本概念,运行过容器,熟悉docker镜像的基础知识,了解镜像的分层结构。最好是负责docker镜像的构建(使用dockerbuild命令创建自己的镜像).每行的第一个单词是命令,后面所有的字符串都是这个命令的参数。Dockerfile支持的命令和使用方法可以参考官方文档,这里不再赘述。运行dockerbuild命令时,整个构建过程如下:读取Dockerfile文件,发送给dockerdaemon读取当前目录下的所有文件(context),发送给dockerdaemon解析Dockerfile并处理它变成命令加上相应的参数结构,依次循环遍历所有命令,并为每个命令调用相应的处理函数。每个命令(FROM除外)都会在一个容器中执行,执行结果会生成一个新的镜像来标记最终生成的镜像。Labels写Dockerfile的一些好的实践1.使用统一的基础镜像有些文章讲优化镜像,提倡使用尽可能小的基础镜像,比如busybox或者alpine。我更喜欢使用大家熟悉的统一基础镜像,比如ubuntu、centos等,因为基础镜像只需要下载一次,就可以共享,不会造成存储空间的过多浪费。它的好处是这些镜像的生态比较完整,方便我们安装软件和调试问题。2、动静分离。经常变化的内容和基本不变化的内容应该分开。变化不大的内容放在下层,创建不同的基础图片供上层使用。比如可以创建各种语言的基础镜像,如python2.7、python3.4、go1.7、java7等,这些镜像包含最基础的语言库,各组可以继续构建应用级镜像在他们。3.极简原则:只安装必要的东西很多人在构建镜像的时候,都有种把可能用到的东西都打包进镜像的冲动。为了遏制这种思想,图像应该只包含必要的内容,而可以包含或不能包含的任何内容都不应包含。因为镜像的扩展非常容易,运行容器的时候修改也很方便。这样可以保证图像越小越好,构建时间越快越好,同时也保证了以后传输速度更快,节省网络资源。4.一个原则:每个图像只有一个功能。不要在容器中运行多个不同功能的进程。每个镜像只安装一个应用程序包和文件。需要交互的程序通过pods(kubernetes提供的特性)或者容器之间的Networking进行通信。这样可以保证模块化,不同的应用可以单独维护和升级,也可以减小单个镜像的体积。5.使用更少的层虽然看起来不同的命令尽可能地分开,但是当写成多个命令时容易阅读和理解。但是这样会导致镜像层数过多,不便于管理和分析镜像,而且镜像层数有限。尽量将相关内容放在同一层,并用换行符分隔,这样可以进一步缩小图像的体积,更便于查看图像的历史。运行apt-getupdate\&&apt-getinstall-y--no-install-recommends\bzr\cvs\git\mercurial\subversion\&&aptgetclean6。减少每一层的内容虽然只安装必要的内容,但在这个过程中也可能产生额外的内容或临时文件,我们尽量将每一层安装的东西保持在最低限度。比如使用--no-install-recommends参数告诉apt-get不要安装推荐的软件包。安装完软件包后,清空/var/lib/apt/list/缓存,删除中间文件:比如删除下载的压缩包中的临时文件:如果是命令生成的临时文件,要及时删除。7、不要单独修改Dockerfile中文件的权限。因为docker镜像是分层的,任何修改都会增加一个新的层,修改文件或目录权限也是如此。如果有单独修改大文件或目录权限的命令,会复制这些文件,容易导致镜像过大。解决方法也很简单,要么在将文件添加到Dockerfile之前设置文件的权限和用户,要么在容器启动脚本(入口点)中进行这些更改,要么复制文件并一起修改权限(这样只会增加层)。8.使用缓存加速构建。如果Docker发现某个层已经存在,它会直接使用现有的层,而不会再次重新运行它。如果你连续运行几次dockerbuild,你会发现第二次运行很快就结束了。但是从1.10版本开始,ContentAddressableStorage的引入导致缓存功能失效。目前引入了--cache-from参数来手动指定一个镜像使用其缓存。9.版本控制和自动构建最好将Dockerfile和对应的应用代码放入版本控制,即可自动构建镜像。这样做的好处是可以跟踪每个版本镜像的内容,方便了解不同镜像之间的差异,有利于调试和回滚。另外,如果运行镜像的参数或环境变量较多,应该有相应的文档进行说明,并且文档应该随着Dockerfile的变化而更新,这样任何人都可以通过参考文档轻松使用镜像下载图像我不知道如何使用它。
