11

I am building a linux docker image on an M1 mac (FROM ruby:3.0.2-alpine3.12 if it matters).

When I attempt to perform a bundle exec in my container, ruby complains that it is unable to load nokogiri. If I simply start ruby and try to require nokogiri I get the same result:

bash-5.0# irb
irb(main):001:0> require 'nokogiri'
<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>'

The gem is installed

ls -la /app/vendor/bundle/ruby/3.0.0/gems/

<snip>
drwxr-xr-x    6 root     root          4096 Feb  2 22:43 nokogiri-1.13.1-aarch64-linux
<snip

One somewhat curious thing is

bash-5.0# ruby --version
ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [aarch64-linux-musl]

I don't think the musl platform is causing the mismatch. Our production machines are amd64 and there's a similar amd64/amd64-musl mismatch there, but they run the containers correctly.

Is there a way to get this working?

Workaround

I have been able to work around this by disabling the use of precompiled gems when bundling, but it would be nice to not have to do so. (We have a mixed M1/Intel dev group and the cross compile for the foreign architecture seems to be pretty lengthy).

Andy Davis
  • 1,393
  • 1
  • 13
  • 24

2 Answers2

45

I had a similar problem with a Rails app that has dependency on Nokogiri running on an Alpine based container on my Macbook M1. Here is what I did:

  1. Reading the Nokogiri documentation, I found out that aarch64-linux (the architecture used inside the Docker container) is actually supported, but it requires glibc >= 2.29.

  2. I am far from being an expert but, as far as I know, Alpine distributions don't include glibc but musl. Fortunately, there are ways to run programs that need glibc in Alpine.

  3. I personally followed the first option, that is, I installed gcompat. I just needed to add gcompat to the list of packages to install in my Dockerfile.

    RUN apk add --no-cache ... gcompat

  4. After that change, things went smoothly and the Rails app started up with no issues.

Again, I am not an expert and the above might be inaccurate, but it did the magic for me. I hope it can help you too.

Pedro Galan
  • 647
  • 6
  • 10
-1

Another solution is to add platform: linux/x86_64 to the service that requires it and rebuild the image with docker compose build but compared to Pedro's solution, it seems to me that it is more effective and it is faster to build the image.

This worked for me on the Macbook pro M2.