我们有一个 Dockerfile,在某个时刻不希望发生缓存。
目前我们正在使用
ENV CACHE_BUST=$($RANDOM)
经过进一步检查,有趣的是被缓存了:
步骤 1/1:ENV CACHE_BUST=$($RANDOM)
---> 使用缓存
有没有办法从 Dockerfile 内部破坏缓存而不传递唯一的 build-arg
(例如 docker build . --build-arg CACHE_BUST=$(date +%s)
) 在构建步骤中?
最佳答案
更新:回顾这一点,您似乎以两种方式错误地注入(inject)了缓存清除选项:
ENV
不是ARG
$(x)
语法不是变量扩展,您需要大括号 (${}
),而不是括号 ($()
).
要在下一个运行行中断缓存,语法为:
ARG CACHE_BUST
RUN echo "command with external dependencies"
然后构建:
docker build --build-arg CACHE_BUST=$(date +%s) .
为什么会这样?因为在构建过程中,ARG
的值会作为环境变量注入(inject)到 RUN
命令中。更改环境变量会导致新版本的缓存未命中。
要破坏缓存,需要更改其中一个输入。如果正在运行的命令相同,即使该命令具有已更改的外部依赖项,缓存也将被重用,因为 docker 无法看到这些外部依赖项。
解决此问题的选项包括:
- 传递会更改的构建参数(例如将其设置为日期戳)。
- 通过 COPY 或 ADD 更改包含在镜像中的文件。
- 使用
--no-cache
选项运行构建。
由于您不想执行选项 1,因此有一种方法可以在特定行上执行选项 3,但前提是您可以将 Dockerfile 分成两部分。第一个 Dockerfile 包含您今天所拥有的所有行,直到您想要破坏缓存为止。然后第二个 Dockerfile 有一个 FROM 行依赖于第一个 Dockerfile,您可以使用 --no-cache
选项构建它。例如
Dockerfile1:
FROM base
RUN normal steps
Dockerfile2
FROM intermediate
RUN curl external.jar>file.jar
RUN other lines that cannot be cached
CMD your cmd
然后构建:
docker build -f Dockerfile1 -t intermediate .
docker build -f Dockerfile2 -t final --no-cache .
我能想到的唯一其他选择是使用BuildKit创建一个新的前端它允许您注入(inject)显式缓存中断或导致缓存中断的唯一变量。
关于docker - 在不提供外部构建参数的情况下,在 Dockerfile 中破坏缓存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55619593/