【发布时间】:2020-01-18 15:43:49
【问题描述】:
我正在尝试使用 docker 的 buildkit 来缓存构建之间捆绑安装的结果。我正在使用新的 RUN mount=type-cache... 选项来允许为后续构建缓存 bunder 结果。但是,似乎没有任何东西被缓存。
我将 docker 19.03.01 用于 docker 客户端和服务器。我已经在构建 vie envar DOCKER_BUILDKIT=1 上启用了 buildkit 请注意,ssh 挂载似乎正在工作,但缓存挂载却没有。我的 Dockerfile 中有这些行来运行 bundler
# syntax=docker/dockerfile:experimental
FROM ruby:2.4.6
ENV BUNDLE_PATH=/bundler
RUN gem install bundle
RUN mkdir /app && mkdir /bundler
ADD . /app
WORKDIR /app
ENV BUNDLE_PATH=/bundler
RUN mount=type=cache,target=/bundler ls -la /bundler/cache; bundle install
项目目录只能包含一个 Gemfile(称为 Gemfile),其内容如下:
source "https://rubygems.org"
gem "humanize"
gem "i18n"
gem "rake"
我正在按如下方式运行构建:
DOCKER_BUILDKIT=1 docker build . --progress=plain
在第一次运行时,列出/bundler/cache 的尝试按预期失败,并且捆绑程序运行。运行容器会验证所有内容都按预期安装在 /bundler 下。
但是,如果 gemfile 被更改,再次运行 docker build 会得到完全相同的输出——ls 命令失败,并且 bundler 会重建整个 gemfile。我希望 ls 命令能够向我显示上次运行时 /bundler 的内容,并且我希望 bundler install 命令只构建更改后的 gem。
我可以看到在某处创建了缓存,因为docker builder prune 在命令运行后实际上会修剪东西。但是在后续构建中似乎没有使用任何缓存。
例如,这里是第一个构建的运行阶段,移除了 rake gem:
#12 [6/6] RUN mount=type=cache,target=/bundler ls -la /bundler/cache;
bundle...
#12 1.154 ls: cannot access '/bundler/cache': No such file or directory
#12 3.059 Fetching gem metadata from https://rubygems.org/...
#12 3.292 Resolving dependencies...
#12 3.305 Using bundler 1.17.3
#12 3.306 Fetching concurrent-ruby 1.1.5
#12 3.377 Installing concurrent-ruby 1.1.5
#12 3.483 Fetching humanize 2.1.2
#12 3.568 Installing humanize 2.1.2
#12 3.606 Fetching i18n 1.6.0
#12 3.654 Installing i18n 1.6.0
#12 3.691 Bundle complete! 2 Gemfile dependencies, 4 gems now installed.
这符合预期。然后当我将 rake gem 添加到 Gemfile 中并重建时:
#12 [6/6] RUN mount=type=cache,target=/bundler ls -la /bundler/cache;
bundle...
#12 1.186 ls: cannot access '/bundler/cache': No such file or directory
#12 3.355 Fetching gem metadata from https://rubygems.org/...
#12 3.562 Resolving dependencies...
#12 3.579 Fetching rake 12.3.3
#12 3.658 Installing rake 12.3.3
#12 3.718 Using bundler 1.17.3
#12 3.719 Fetching concurrent-ruby 1.1.5
#12 3.875 Installing concurrent-ruby 1.1.5
#12 4.029 Fetching humanize 2.1.2
#12 4.068 Installing humanize 2.1.2
#12 4.103 Fetching i18n 1.6.0
#12 4.142 Installing i18n 1.6.0
#12 4.184 Bundle complete! 3 Gemfile dependencies, 5 gems now installed.
#12 4.184 Bundled gems are installed into `/bundler`
#12 4.184 Post-install message from i18n:
在第二次运行时,我希望看到 ls -la /bundler/cache 成功,并向我展示上次运行时安装的 gem。我还希望 bundler 不会获取和重建刚刚构建的 gem。
这个想法是这个 bunder 安装只是成为 Dockerfile 中的第一阶段,最后阶段只是复制第一阶段的 /bundler 目录的内容。
我觉得我可能误解了 RUN 缓存挂载的确切工作原理,但我对为什么这个简单的示例似乎不起作用感到困惑。任何帮助将不胜感激。
【问题讨论】:
-
什么 gemfile?您讨论它,但在您的示例中没有。见minimal reproducible example。
-
之前有一个 ADD 指令将其添加到 /app。 gemfile 始终存在并构建 - 但似乎没有缓存 bunder 结果。
-
请看上面链接的“完整”部分。
-
编辑后的代码应该很容易重现——谢谢。