Unable to load nokogiri in docker container on M1 Mac
Asked Answered
G

3

12

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).

Glossy answered 2/2, 2022 at 22:54 Comment(0)
O
47

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.

Octo answered 7/2, 2022 at 6:44 Comment(5)
worked like a champ, thanks!Glossy
you saved my day. Thanks!Campus
Thank you so much. This was what I needed!Fidge
This is still not working for me. anything am missing?Nowak
darnit! it just automagically worked after that addition. Not all heroes were capes. Thanks a million, man.Penetralia
H
0

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.

Hypophysis answered 27/7, 2022 at 16:8 Comment(1)
I don't think OP was interested in running it for x86_64, at all.Bullhorn
A
0

You can change the tag on the Ruby image you are using to 'bullseye', because they are based on the arm64 architecture, this architecture is compatible with Apple M1 processors.

EX: FROM ruby:3.0-bullseye

Adriel answered 11/3 at 12:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.