在本地计算机上,我已经构建了latest映像,并docker build在应有的位置运行另一个使用缓存。
然后,将映像作为上载到注册表latest,然后在CI服务器上,提取latest应用程序的映像,以将其用作构建缓存来构建新版本:
docker pull $CONTAINER_IMAGE:latest
docker build --cache-from $CONTAINER_IMAGE:latest \
--tag $CONTAINER_IMAGE:$CI_COMMIT_SHORT_SHA \
.
Run Code Online (Sandbox Code Playgroud)
从构建输出中,我们可以看到的COPY中Gemfile没有使用图片中的大小写latest,而我还没有更新该文件:
Step 15/22 : RUN gem install bundler -v 1.17.3 && ln -s /usr/local/lib/ruby/gems/2.2.0/gems/bundler-1.16.0 /usr/local/lib/ruby/gems/2.2.0/gems/bundler-1.16.1
---> Using cache
---> 47a9ad7747c6
Step 16/22 : ENV BUNDLE_GEMFILE=$APP_HOME/Gemfile BUNDLE_JOBS=8
---> Using cache
---> 1124ad337b98
Step 17/22 : WORKDIR $APP_HOME
---> Using cache
---> 9cd742111641
Step 18/22 : COPY Gemfile $APP_HOME/
---> f7ff0ee82ba2
Step 19/22 : COPY Gemfile.lock $APP_HOME/
---> c963b4c4617f
Step 20/22 : RUN bundle install
---> Running in 3d2cdf999972
Run Code Online (Sandbox Code Playgroud)
旁节点:它在我的本地计算机上运行良好。
查看Docker文档杠杆构建缓存似乎没有在此解释行为,因为Dockerfile和Gemfile均未更改,因此应使用缓存。
是什么让Docker不使用Gemfile缓存?
我尝试使用来复制设置了正确权限的文件,COPY --chown=user:group source dest但仍不使用缓存。
打开Docker论坛主题:https : //forums.docker.com/t/docker-build-not-using-cache-when-copying-gemfile-while-using-cache-from/69186
Eli*_*les 10
--cache-from在过去的几天里,我一直在努力解决Docker构建问题--cache-from,而对于的正确行为,缺少文档也令人感到沮丧,而实际上却存在一些错误信息。
我认为,在我将在这里分享一些见解之后,我终于设法解决了我身边的问题,希望对其他人有用。
--cache-from,顺序很重要!该顺序非常重要,因为在第一个匹配项中,Docker将停止寻找其他匹配项,并将其用于其余所有命令。
当使用多个--cache-from时,将按照用户指定的顺序检查是否有缓存命中。如果其中一幅图像产生命令命中的高速缓存命中,则仅该图像用于其余的构建。
指定多个--cache-from图像有点麻烦。如果两个图像都匹配,则无法(无需多次通过)找出要使用的图像。因此,我们选择第一个(让用户控制优先级),但这可能不是最后我们可以匹配的最长链。如果我们允许针对某个命令匹配一个映像,然后又切换到链较长的另一个映像,则由于我们仅验证历史记录和缓存层,因此可能会泄漏映像之间的某些信息。目前,我已将其保留下来,这样,如果我们找到匹配项,则其余命令只使用该目标图像。
--cache-from是专有的:将不使用本地Docker缓存这意味着它不会添加新的缓存源,您提供的图像标签将是Docker构建的唯一缓存源。
即使您只是在本地构建了相同的映像,下一次为它运行docker build时,为了从缓存中受益,您还需要:
提供正确的标签--cache-from(并具有正确的优先级);要么
完全不使用--cache-from(以便它将使用本地构建缓存)
例如,如果您有一个基于的图像docker:stable并docker:stable进行了更新,则由于基础图像的层已更改,因此图像的缓存版本将不再有效。
这就是为什么,如果您要配置CI构建,那么它对于docker pull基础映像也很有用,并将其包含在中--cache-from,如本注释在另一个Github讨论中所述。
我一直在努力解决这个问题,在我的例子中,当校验和可能发生变化时,我使用了 COPY(但仅在技术上,内容在功能上是相同的)。所以,我这样解决:
Dockerfile:
ARG builder_image=base-builder
# Compilation/build stage
FROM golang:1.16 AS base-builder
RUN echo "build the app" > /go/app
# This step is required to facilitate docker cache. With the definition of a `builder_image` build tag
# we can essentially skip the build stage and use a prebuilt-image directly.
FROM $builder_image AS builder
# myapp docker image
FROM ubuntu:20.04 AS myapp
COPY --from=builder /go/app /opt/my-app/bin/
Run Code Online (Sandbox Code Playgroud)
然后,我可以运行以下命令:
ARG builder_image=base-builder
# Compilation/build stage
FROM golang:1.16 AS base-builder
RUN echo "build the app" > /go/app
# This step is required to facilitate docker cache. With the definition of a `builder_image` build tag
# we can essentially skip the build stage and use a prebuilt-image directly.
FROM $builder_image AS builder
# myapp docker image
FROM ubuntu:20.04 AS myapp
COPY --from=builder /go/app /opt/my-app/bin/
Run Code Online (Sandbox Code Playgroud)
这样我们就可以强制 Docker 使用预构建的镜像作为缓存。
对于COPY要缓存的命令,校验和需要与正在复制的源上相同。您可以比较缓存映像与刚刚构建的映像之间的 docker 历史记录输出中的校验和。最重要的是,除了文件内容之外,校验和还包括文件所有者和文件权限等元数据。文件内的空格更改(例如更改 Linux 和 Windows 样式之间的换行符)也会影响这一点。如果您从存储库下载代码,则元数据(例如所有者)可能与缓存的值不同。
| 归档时间: |
|
| 查看次数: |
1037 次 |
| 最近记录: |