Docker 构建总在重下依赖?先看这三处缓存断点
很多人第一次把 Python 或 Node 服务放进镜像,都会碰上同一件事:业务代码只改了一行,docker build 却从安装依赖重新开始,进度条再走好几分钟。这很少是镜像源突然坏了,更多是构建缓存被提前打断。
Docker 按 Dockerfile 从上到下做层缓存。某一层的输入变了,它后面的每一层都要重做。依赖安装如果写在复制全部源码之后,就会被每一次小改动拖下水。把这个顺序调整对,日常构建往往能从数分钟掉到十几秒。
第一处是 COPY 的顺序。把依赖清单单独复制进去,先执行安装,再复制其余源码。这样业务文件变化时,安装那一层仍然可以命中缓存,只有最后的代码层重建。如果一上来就 COPY . .,README 多一个标点,依赖层也会一起失效。清单文件本身变动时重装是合理的,不该让无关文件拥有同样的破坏力。
第二处是 ARG 和 ENV 放在了安装命令前面。构建参数一变,后面的 RUN 全部作废。只影响运行时的变量,比如监听端口、日志级别,应挪到依赖安装完成之后。需要在安装阶段使用的参数才留在前面,并且尽量保持默认值稳定,避免持续集成每次塞进时间戳或随机串。
第三处是构建上下文。没有 .dockerignore 时,.git、本地虚拟环境、日志和编辑器缓存都会送进守护进程。上下文校验和一变,第一条 COPY 就对不上缓存。把这些目录排除掉,构建会变快,镜像也不容易把临时文件带进层里。排除规则写进仓库,和 Dockerfile 一起评审。
可以做一次三步自测。连续构建两次,第二次应在依赖层看到 CACHED。然后只改一个业务文件再构建,依赖层仍应命中。若第二次就全量重跑,按上面三处倒序检查。这套习惯不绑定某一家云,换到任何支持 Dockerfile 的构建服务都一样适用。
最后补一句实践里容易忽略的事。缓存命中只说明输入没变,不说明依赖内容永远正确。基础镜像更新、漏洞修复、锁文件升级,都应该主动让安装层失效一次。可以在清单文件里留一行注释记录本次依赖升级的原因,下次回看构建日志时,就能分清是缓存正常命中,还是该重装却被旧层挡住。把这三处断点和一次主动失效放在同一份 Dockerfile 约定里,团队里谁来改服务都不会把构建时间打回原点。
- 点赞
- 收藏
- 关注作者
评论(0)