在 vendor/cache 和 Docker 中使用 vendored gem

Using vendored gems in vendor/cache with Docker

这是我的 docker 有效文件:

FROM ruby:2.6.6
WORKDIR /home/app/webapp
COPY . /home/app/webapp/
RUN bundle install
# Start the main process.
CMD ['/home/app/webapp/entrypoint.sh']

这工作正常,但它每次都会捆绑安装!相反,我在 git 源本身中直接拥有 /vendor/cache 中的所有 gems 供应商。

$ ls vendor/cache
<..snip long list.>
rake-13.0.1.gem
rails-5.2.4.1.gem
rails-controller-testing-1.0.4.gem
rails-dom-testing-2.0.3.gem
rails-html-sanitizer-1.3.0.gem
rails-i18n-5.1.3.gem
rails-ujs-0.1.0.gem
sass-rails-5.0.8.gem
sprockets-rails-3.2.1.gem
<..snip long list.>

根据捆绑文档:https://bundler.io/bundle_install.html,这应该像它所说的那样工作:

While installing gems, Bundler will check vendor/cache and then your system's gems. If a gem isn't cached or installed, Bundler will try to install it from the sources you have declared in your Gemfile.

当我在没有 docker 的 mac 上捆绑时,这确实有效,如下所示:

$ bundle 
Using rake 13.0.1
Using rails 5.2.4.1
Using rails-controller-testing 1.0.4
Using rails-i18n 5.1.3
Using rails-ujs 0.1.0
Using sidekiq-pro 4.0.4
Updating files in vendor/cache
Bundle complete! 144 Gemfile dependencies, 304 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

因此,我修改了 docker 文件以利用缓存。所以我只捆绑安装一次并将其保存为一个层。然后,对于任何代码更改,都不需要再次安装 bundle

FROM ruby:2.6.6
WORKDIR /home/app/webapp
COPY Gemfile Gemfile.lock /vendor/cache/ /home/app/webapp/
RUN bundle install
COPY . /home/app/webapp/
# Start the main process.
CMD ['/home/app/webapp/entrypoint.sh']

现在,当我尝试构建它时,出现以下错误:

$ docker-compose build
redis uses an image, skipping
db uses an image, skipping
Building rails
Step 1/6 : FROM ruby:2.6.6
 ---> 107c48f680c0
Step 2/6 : WORKDIR /home/app/webapp
 ---> Using cache
 ---> f23fc51ac8ba
Step 3/6 : COPY Gemfile Gemfile.lock /vendor/cache/ /home/app/webapp/
 ---> 0d1f451b7ee0
Step 4/6 : RUN bundle install
 ---> Running in 5768798c1bcd
Warning: the running version of Bundler (1.17.2) is older than the version that created the lockfile (1.17.3). We suggest you upgrade to the latest version of Bundler by running `gem install bundler`.
Fetching gem metadata from https://rubygems.org/.......
Could not find sidekiq-pro-4.0.4 in any of the sources
ERROR: Service 'rails' failed to build: The command '/bin/sh -c bundle install' returned a non-zero code: 7

然而, sidekiq-pro gem 已经在 vendor/cache

$ ls vendor/cache | grep sidekiq-pro
sidekiq-pro-4.0.4.gem

所以这确实适用于没有 docker 的本地 mac,因为捆绑程序从缓存中获取 sidekiq gem,但它不适用于 docker。知道我还能尝试什么吗?

我设法解决了这个问题。需要编辑 Dockerfile 以复制 vendor/cache 处的 gem。这是修改后的 gemfile,它可以工作并利用 docker 缓存

FROM ruby:2.6.6
WORKDIR /home/app/webapp
COPY Gemfile Gemfile.lock /home/app/webapp/
COPY vendor/cache /home/app/webapp/vendor/cache/
RUN bundle install
COPY . /home/app/webapp/
# Start the main process.
CMD ['/home/app/webapp/entrypoint.sh'] 

在此处添加答案,以防其他人遇到同样的错误。谢谢你看。