問題
M1macでDockerのrubyイメージからを使おうとすると、nokogiriの部分でエラーが出ます。
% docker run --rm -it ruby:3.0.3-buster bash root@489921d6a766:/# gem i nokogiri Fetching nokogiri-1.13.4-aarch64-linux.gem Successfully installed nokogiri-1.13.4-aarch64-linux 1 gem installed root@489921d6a766:/# irb irb(main):001:0> require 'nokogiri' ERROR: It looks like you're trying to use Nokogiri as a precompiled native gem on a system with glibc < 2.17: /lib/aarch64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by /usr/local/bundle/gems/nokogiri-1.13.4-aarch64-linux/lib/nokogiri/3.0/nokogiri.so) - /usr/local/bundle/gems/nokogiri-1.13.4-aarch64-linux/lib/nokogiri/3.0/nokogiri.so If that's the case, then please install Nokogiri via the `ruby` platform gem: gem install nokogiri --platform=ruby or: bundle config set force_ruby_platform true Please visit https://nokogiri.org/tutorials/installing_nokogiri.html for more help. /usr/local/bundle/gems/nokogiri-1.13.4-aarch64-linux/lib/nokogiri/extension.rb:7:in `require_relative': /lib/aarch64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by /usr/local/bundle/gems/nokogiri-1.13.4-aarch64-linux/lib/nokogiri/3.0/nokogiri.so) - /usr/local/bundle/gems/nokogiri-1.13.4-aarch64-linux/lib/nokogiri/3.0/nokogiri.so (LoadError) from /usr/local/bundle/gems/nokogiri-1.13.4-aarch64-linux/lib/nokogiri/extension.rb:7:in `<top (required)>' from /usr/local/bundle/gems/nokogiri-1.13.4-aarch64-linux/lib/nokogiri.rb:10:in `require_relative' from /usr/local/bundle/gems/nokogiri-1.13.4-aarch64-linux/lib/nokogiri.rb:10:in `<top (required)>' from <internal:/usr/local/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:160:in `require' from <internal:/usr/local/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:160:in `rescue in require' from <internal:/usr/local/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:149:in `require' from (irb):1:in `<main>' from /usr/local/lib/ruby/gems/3.0.0/gems/irb-1.3.5/exe/irb:11:in `<top (required)>' from /usr/local/bin/irb:23:in `load' from /usr/local/bin/irb:23:in `<main>' <internal:/usr/local/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:85:in `require': cannot load such file -- nokogiri (LoadError) from <internal:/usr/local/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:85:in `require' from (irb):1:in `<main>' from /usr/local/lib/ruby/gems/3.0.0/gems/irb-1.3.5/exe/irb:11:in `<top (required)>' from /usr/local/bin/irb:23:in `load' from /usr/local/bin/irb:23:in `<main>' irb(main):002:0>
原因は、Nokogiriが1.11あたりからプリコンパイルされて配布されるようになりました。そのバイナリは、glibc 2.17でコンパイルされています。
しかしながら、arm用にコンパイルされたnokogiriが参照している /lib/aarch64-linux-gnu/libm.so.6
が2.29を必要としているっぽくてエラーになります。
解決方法
静的リンクするか、独自でコンパイルするのが良さそうです。静的リンクはバイナリサイズがでかくなりそうなので独自でコンパイルします。
Bundlerを使っている場合
Bundler使っている場合は以下を打って自分でコンパイルするように設定します。
# bundler 2.1以降 % bundle config set force_ruby_platform true # bundler 2.0以前 % bundle config force_ruby_platform true
そうすると、.bundle/configに以下が入ります。
--- BUNDLE_FORCE_RUBY_PLATFORM: "true"
もし、.bundleディレクトリを.gitignoreで無視するような設定を書いていたり、ユーザ側で設定した.bundleディレクトリを使うようにしている場合はホームディレクトリの設定ファイルに書き込んであげるのがよいです。
bundle config set --global force_ruby_platform true
実行例
% docker run --rm -it ruby:3.0.3-buster bash root@11a428c7e8da:/# bundle config set force_ruby_platform true root@11a428c7e8da:/# bundle init Writing new Gemfile to //Gemfile root@11a428c7e8da:/# bundle add nokogiri Fetching gem metadata from https://rubygems.org/....... Resolving dependencies... Fetching gem metadata from https://rubygems.org/....... Resolving dependencies... Using bundler 2.2.32 Fetching racc 1.6.0 Fetching mini_portile2 2.8.0 Installing racc 1.6.0 with native extensions Installing mini_portile2 2.8.0 Fetching nokogiri 1.13.4 Installing nokogiri 1.13.4 with native extensions root@11a428c7e8da:/# bundle exec irb irb(main):002:0> require 'nokogiri' => true
Bundlerを使っていない場合
--platform=ruby
オプションをつけてインストールします。
root@b4ca7905b3a5:~# gem install nokogiri --platform=ruby Fetching nokogiri-1.13.4.gem Building native extensions. This could take a while... Successfully installed nokogiri-1.13.4 1 gem installed root@b4ca7905b3a5:~# irb irb(main):001:0> require 'nokogiri' => true root@b4ca7905b3a5:/# gem list|grep nokogiri nokogiri (1.13.4)
手元での変更
結果的に手元のプロジェクトでは以下のような変更をDockerfileに行いました。
+ RUN bundle config set --global force_ruby_platform true
参考資料
詳細はこちらのissueにかかれています。
Feedback and final to-do items for precompiled native gems on Linux and OSX · Issue #2075 · sparklemotion/nokogiri
This issue exists to capture feedback and action items about the precompiled native gems for Linux and OSX that we're sh...
不確実情報
環境によっては、arm用のbinaryがインストールされたりもするので、これが実現すればコンパイルの時間が取られなくて良いのでどういったときにこのような設定ができるのかを検証中です。
Comments