Docker构建layer:2时提示‘layer does not exist’的问题求助
问题分析:Docker构建报错‘layer does not exist’与缓存机制的关联
这个问题确实和Docker的构建缓存机制直接相关,而且是你使用的Docker 19.03.13-ce版本中存在的一个已知缓存bug,在链式镜像构建(layer:2基于layer:1,layer:1基于layer:base)的场景下被触发了。
为什么会出现这个错误?
我们来拆解你的构建流程和Docker缓存的逻辑:
- 你的
variable-base.dockerfile里有两个独立的ADD指令:
每个ADD installer.sh /apps/ ADD ${config} /apps/ADD都会生成一个单独的镜像层,Docker会为每个层生成基于文件内容哈希的缓存键。 - 当构建
layer:1时,ARG config的值是config-1.ini,两个ADD指令分别生成对应的层;构建layer:2时,ARG config变为config-2.ini,Docker会尝试复用layer:1中未变化的缓存层(比如ADD installer.sh的层,因为文件内容没改),重新执行第二个ADD指令。 - 在Docker 19.03的部分版本中,存在一个缓存关联的bug:当复用动态ARG生成的镜像缓存层时,Docker无法正确追踪上层镜像对这些缓存层的依赖关系,导致在构建
layer:2时错误地认为某个中间层不存在,抛出layer does not exist的报错。
为什么合并ADD指令后错误消失?
当你把两个ADD合并成一行:
ADD installer.sh ${config} /apps/
Docker只会生成一个镜像层,这个层的缓存键同时包含installer.sh和${config}的内容哈希。当构建layer:2时,因为config-2.ini和config-1.ini内容不同,整个ADD指令会完全重新执行,不会触发缓存复用的逻辑,自然也就避开了那个缓存bug。
验证与解决方案
验证方法
如果想确认是缓存的问题,可以尝试:
- 先执行
docker build --no-cache构建layer:1,再构建layer:2,即使保留两个独立的ADD指令,也不会出现报错(因为强制跳过了缓存复用)。
解决方案
- 保留合并
ADD的方式:这是最简单的规避方法,同时还能减少镜像的层数,优化镜像体积。 - 升级Docker版本:这个缓存bug在Docker 20.10及以上的稳定版本中已经被修复,升级后可以正常使用独立的
ADD指令。 - 禁用缓存构建:如果暂时无法升级,可以在构建
layer:2时添加--no-cache参数,强制不使用缓存,但会增加构建时间。
内容的提问来源于stack exchange,提问作者Nishant
相关产品推荐
相关产品推荐

