代码之家  ›  专栏  ›  技术社区  ›  ZedTuX

Docker Build在使用--cache from复制gemfile时不使用缓存

  •  0
  • ZedTuX  · 技术社区  · 7 年前

    在我的本地机器上,我已经建立了 latest 映像,并运行另一个 docker build 应该在任何地方使用缓存。

    然后我将图像作为 最新的 ,然后在我的ci服务器上, 最新的 要将我的应用程序用作生成缓存以生成新版本的图像:

    docker pull $CONTAINER_IMAGE:latest
    
    docker build --cache-from $CONTAINER_IMAGE:latest \
                 --tag $CONTAINER_IMAGE:$CI_COMMIT_SHORT_SHA \
                 .
    

    从构建输出中我们可以看到 COPY Gemfile 不使用来自 最新的 图像,而我还没有更新该文件:

    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
    

    旁侧节点 :它在我的本地机器上运行良好。

    查看Docker文档 Leverage build cache 似乎无法解释这里的行为,因为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

    1 回复  |  直到 7 年前
        1
  •  2
  •   Elias Dorneles    7 年前

    我一直在为Docker Build和 --cache-from 在过去的几天里,缺少关于 --从 ,而在野外也有一些误传。

    我想我终于解决了我这边的问题,我在这里分享了一些见解,希望对其他人有用。

    当提供多个 --从 ,顺序很重要!

    顺序很重要,因为在第一场比赛中, Docker将停止寻找其他匹配项,它将使用该匹配项执行所有其他命令 .

    This is explained by the fellow who implemented the feature in the Github PR :

    当使用multiple--cache from时,将按用户指定的顺序检查缓存命中率。如果其中一个映像对某个命令产生缓存命中,则该映像仅用于生成的其余部分。

    还有 a lenghtier explanation in the initial ticket proposal :

    从图像中指定多个缓存有点问题。如果两个图像都匹配,则无法(不执行多次传递)确定要使用的图像。所以我们选择第一个(让用户控制优先级),但这可能不是我们最终可以匹配的最长链。如果我们允许在某些命令中对一个图像进行匹配,然后切换到具有较长链的另一个图像,我们可能会在图像之间泄漏一些信息,因为我们只验证缓存的历史和层。目前我留下了它,所以如果我们得到一个匹配,我们只使用这个目标图像的其余命令。

    使用 --从 是独占的:不使用本地Docker缓存

    这意味着它不会添加新的缓存源,您提供的图像标记将是Docker构建的唯一缓存源。

    即使您只是在本地构建相同的映像,下次运行Docker Build时,为了从缓存中获益,您需要:

    1. 提供正确的标签 --从 (并具有正确的优先权);或

    2. 不使用 --从 完全(以便它使用本地生成缓存)

    如果父映像更改,缓存将失效

    例如,如果您有一个基于 docker:stable Docker:稳定 更新后,图像的缓存生成将不再有效,因为基础图像的层已更改。

    这就是为什么,如果要配置CI生成, it can be useful to docker pull the base image as well and include it in the --cache-from , as mentioned in this comment in yet another Github discussion .

        2
  •  0
  •   BMitch    7 年前

    对于一个 COPY 命令要缓存,则要复制的源上的校验和必须相同。您可以比较Docker历史输出中缓存映像和您刚刚构建的映像之间的校验和。最重要的是,除了文件内容外,校验和还包括诸如文件所有者和文件权限之类的元数据。文件中的空白更改(如在Linux和Windows样式之间更改为换行)也会影响此操作。如果从repo下载代码,元数据(如所有者)可能与缓存值不同。

    推荐文章