Docker上的Rails-由于未构建扩展而忽略GEM

时间:2020-03-31 16:41:27

标签: ruby-on-rails docker

过去两天来,我一直在为这个错误而疯狂。我正在尝试对Rails 6应用程序进行Docker

根据this,我分两个阶段制作Dockerfile,以最大程度地减少生成的图像的大小。一切似乎都按预期工作:我bundle installyarn install在构建阶段,然后将其复制到最终阶段。但是,当尝试通过bundle exec rails s实际启动服务器时,出现以下错误:

Could not find nokogiri-1.10.9 in any of the sources

在相关容器中运行bash时,我们可以检查bundle中是否知道宝石。但是,bundle list失败,出现上述错误。只需运行bundle,我们就会发现一个线索:

Ignoring bcrypt-3.1.13 because its extensions are not built. Try: gem pristine bcrypt --version 3.1.13
Ignoring bootsnap-1.4.6 because its extensions are not built. Try: gem pristine bootsnap --version 1.4.6
Ignoring ffi-1.12.2 because its extensions are not built. Try: gem pristine ffi --version 1.12.2
Ignoring msgpack-1.3.3 because its extensions are not built. Try: gem pristine msgpack --version 1.3.3
Ignoring nio4r-2.5.2 because its extensions are not built. Try: gem pristine nio4r --version 2.5.2
Ignoring nokogiri-1.10.9 because its extensions are not built. Try: gem pristine nokogiri --version 1.10.9
Ignoring pg-1.2.3 because its extensions are not built. Try: gem pristine pg --version 1.2.3
Ignoring puma-4.3.3 because its extensions are not built. Try: gem pristine puma --version 4.3.3
Ignoring sassc-2.2.1 because its extensions are not built. Try: gem pristine sassc --version 2.2.1
Ignoring websocket-driver-0.7.1 because its extensions are not built. Try: gem pristine websocket-driver --version 0.7.1

在构建阶段,运行bundle install并将deployment选项设置为true,这意味着所有gems都安装在本地vendor/bundle中。实际上,我们可以看到nokogiri和其余缺少的gem以及它们的内置扩展名实际上在该文件夹中:

/usr/src/app> ls -R vendor/bundle/ruby/2.6.0/extensions/x86_64-linux-musl/2.6.0/
# ...
vendor/bundle/ruby/2.6.0/extensions/x86_64-linux-musl/2.6.0/nokogiri-1.10.9:
gem.build_complete  gem_make.out        mkmf.log            nokogiri

vendor/bundle/ruby/2.6.0/extensions/x86_64-linux-musl/2.6.0/nokogiri-1.10.9/nokogiri:
nokogiri.so
# ...

当然,可以通过安装相关的构建依赖项然后运行bundle install来在最终映像中解决该问题。在进行此操作之前,我们可以看到nokogiri的编译库在哪里,bundle无法找到:

/usr/src/app > find / -name nokogiri.so
/usr/src/app/vendor/bundle/ruby/2.6.0/extensions/x86_64-linux-musl/2.6.0/nokogiri-1.10.9/nokogiri/nokogiri.so
/usr/src/app/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.9/ext/nokogiri/nokogiri.so
/usr/src/app/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.9/lib/nokogiri/nokogiri.so

运行bundle install之后,bundle可以找到nokogiri很好。但是在哪呢?

/usr/src/app > find / -name nokogiri.so
/usr/src/app/vendor/bundle/ruby/2.6.0/extensions/x86_64-linux-musl/2.6.0/nokogiri-1.10.9/nokogiri/nokogiri.so
/usr/src/app/vendor/bundle/ruby/2.6.0/extensions/x86_64-linux/2.6.0/nokogiri-1.10.9/nokogiri/nokogiri.so
/usr/src/app/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.9/ext/nokogiri/nokogiri.so
/usr/src/app/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.9/lib/nokogiri/nokogiri.so

啊哈!因此,在构建阶段,无论是什么,我们都需要为x86_64-linux平台而不是x86_64-linux-musl平台进行构建。问题:我们如何做到这一点?

bundle config set specific_platform x86_64-linux

我已经在构建过程中尝试设置以上设置,但它不起作用。有什么想法吗?

这篇文章足够长:因此,这里是指向我的Dockerfile的链接。如果您想自己尝试,请确保使用docker-compose up来启动必要的psql服务器。

0 个答案:

没有答案