Docker 中禁用特定 RUN 命令的缓存

我在Dockerfile中有一些RUN命令,我想在每次构建Docker映像时使用-no-cache运行这些命令。

我理解docker build --no-cache将禁用整个Dockerfile的缓存。

是否可以为特定的 RUN 命令禁用缓存?

108592 次浏览

不是直接的,但是你可以把你的Dockerfile分成几个部分,构建一个镜像,然后从这个镜像开始到下一个Dockerfile,然后构建这个镜像,有缓存或者没有缓存

截至2016年2月,这是不可能的。

该特性已在GitHub请求

在想要禁用缓存的区域之前,总是可以插入一些无意义且运行成本低的命令。

正如本期评论中提出的,可以添加一个构建参数块(名称可以是任意的):

ARG CACHEBUST=1

并在每次运行时通过添加--build-arg CACHEBUST=$(date +%s)作为docker build参数来修改其值(value也可以是任意的,这里是当前datetime,以确保其在不同运行时的唯一性)。

当然,这也会禁用所有后续块的缓存,因为中间映像的哈希和将是不同的,这使得真正的选择性缓存禁用成为一个不平凡的问题,考虑到docker当前的工作方式。

另一种快速的破解方法是在命令之前写一些随机字节

RUN head -c 5 /dev/random > random_bytes && <run your command>

写出5个随机字节,这将迫使缓存丢失

该功能是一周前添加的。

ARG FOO=bar


FROM something
RUN echo "this won't be affected if the value of FOO changes"
ARG FOO
RUN echo "this step will be executed again if the value of FOO changes"


FROM something-else
RUN echo "this won't be affected because this stage doesn't use the FOO build-arg"

https://github.com/moby/moby/issues/1996#issuecomment-550020843

使用

ADD "https://www.random.org/cgi-bin/randbyte?nbytes=10&format=h" skipcache

在RUN行之前,你想一直运行。这是因为ADD总是会获取文件/URL,并且上面的URL在每个请求上生成随机数据,然后Docker比较结果,看看它是否可以使用缓存。

我也测试过这个,效果很好,因为它不需要任何额外的Docker命令行参数,而且还可以从Docker-compose中工作。Yaml文件:)

我相信这比@steve的回答略有改进:

RUN git clone https://sdk.ghwl;erjnv;wekrv;qlk@gitlab.com/your_name/your_repository.git


WORKDIR your_repository


# Calls for a random number to break the cahing of the git clone
# (https://stackoverflow.com/questions/35134713/disable-cache-for-specific-run-commands/58801213#58801213)
ADD "https://www.random.org/cgi-bin/randbyte?nbytes=10&format=h" skipcache
RUN git pull

这使用了git克隆的Docker缓存,但随后运行了存储库的非缓存更新。

出现工作,它是更快-但非常感谢@steve提供的基本原则。

如果你的目标是包括来自Github(或类似)的最新代码,你可以使用Github API(或等效)获取有关最新提交的信息,使用ADD命令。
docker build将始终从ADD命令中获取URL,如果响应与上次docker build运行时接收到的响应不同,则它将不使用后续的缓存层

如。

ADD "https://api.github.com/repos/username/repo_name/commits?per_page=1" latest_commit
RUN curl -sLO "https://github.com/username/repo_name/archive/main.zip" && unzip main.zip

基于@Vladislav的解决方案以上,我在Dockerfile中使用

ARG CACHEBUST=0

从这里开始使建立缓存无效。

但是,不是传递日期或其他随机值,而是调用

docker build --build-arg CACHEBUST=`git rev-parse ${GITHUB_REF}` ...

其中GITHUB_REF是使用最新提交哈希的分支名称(例如main)。这意味着只有当我构建映像的分支自docker build的最后一次运行以来已经提交时,docker的构建缓存才会失效。