Docker 镜像在build的过程中,默认会有一套缓存机制。
用自己的语言直白描述 ,能更容易记住呢。
Docker 镜像默认是一层一层的叠加上去。dockerfile中的每一行,对应就是一层。
每次构建,Docker会比对每一层是否有变化,如果构建命令没有–no-cache=true 参数,默认都会尽量用上缓存。
Docker如何判断这一层是否变化呢。ADD,COPY的层,docker会去比对文件,计算文件的校验和。(校验和中不考虑最后修改和最后访问时间)。其余的层,会去比对字符串。一旦其中一层发生了变化,在此之上的所有层,都不会再用到缓存了。
学了原理,当然要知道怎么优雅的使用呢:
- 据一个🌰
1 | from centos-alpha |
如上,我们在调试dockerfile的时候,常常会多次构建,过程中,可能发现缺少依赖包,变反复修改第二层的RUN指令。
而yum update -y ,却是每次最耗时的指令。如果独立层单独一层,就发现速度飞快了。
- 再举一个🌰
1 | FROM node-alpha |
如上,第三层中,每一次npm install 会安装package.json中指定的依赖。而如果一个项目在定型后,package.json在变更的频率会非常少,于是聪明的做法是将其改为
1 | FROM node-alpha |
这样,在第二层package.json文件不变的情况下,在jenkins 构建编译的时候,可以重复利用第二层。速度也随之加快多了。
好的,那么新的问题来了,docker 镜像在开发测试与生产环境物理距离遥远的企业中,应该如何放置呢。像现在的公司,开发测试等环节都在内部的办公机房里。而生产环境远在aws 俄勒冈。镜像的同步受网络条件制约。对此我们内部出现了多种设想。
异地编译,生成镜像。同事说在aws环境内,单独完成生产环境的构建编译镜像封装。
镜像同步,开发测试环境,在稳定后将镜像同步到特定的仓库。改仓库再通过mirror同步到海外的registey。
我选择了2。原因是容器的目的之一,便是将运行环境也纳入到版本控制中,方案一存在巨大的漏洞,两次构建编译,其中存在不确定因素,所以被彻底否决。