在 Docker 的供应商/缓存中使用供应商的 gem

Cur*_*ind 4 ruby-on-rails bundler docker dockerfile

这是我的 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']
Run Code Online (Sandbox Code Playgroud)

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

$ 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.>
Run Code Online (Sandbox Code Playgroud)

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

安装 gems 时,Bundler 将检查供应商/缓存,然后检查系统的 gems。如果 gem 未缓存或安装,Bundler 将尝试从您在 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.
Run Code Online (Sandbox Code Playgroud)

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

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']
Run Code Online (Sandbox Code Playgroud)

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

$ 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
Run Code Online (Sandbox Code Playgroud)

然而,sidekiq-pro gem 已经在供应商/缓存中

$ ls vendor/cache | grep sidekiq-pro
sidekiq-pro-4.0.4.gem
Run Code Online (Sandbox Code Playgroud)

因此,这确实可以在没有 docker 的本地 Mac 上运行,因为捆绑程序会从缓存中获取 sidekiq gem,但它不适用于 docker。知道我还可以尝试什么吗?

Cur*_*ind 6

我设法解决了这个问题。需要编辑 Dockerfile 以在供应商/缓存中复制 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'] 
Run Code Online (Sandbox Code Playgroud)

在这里添加答案,以防其他人遇到同样的错误。谢谢您的关注。