無気力生活 (ノ ´ω`)ノ ~゜

脱力系エンジニア。てきとーに生きてます。

alpine+Railsでの ld-linux-x86-64.so.2: No such file or directory 問題について

使っているイメージ: ruby:2.6.5-alpine

techblog.gmo-ap.jp

この症状と全く同じ。ld-linux-x86-64.soが不足していると言われる。

LoadError: Error loading shared library ld-linux-x86-64.so.2: No such file or directory (needed by /usr/local/bundle/gems/grpc-1.23.0-x86_64-linux/src/ruby/lib/grpc/2.6/grpc_c.so) - /usr/local/bundle/gems/grpc-1.23.0-x86_64-linux/src/ruby/lib/grpc/2.6/grpc_c.so

このときのDockerfileは以下の通り

FROM ruby:2.6.5-alpine
ENV LANG C.UTF-8
ENV BUNDLE_JOBS 4
WORKDIR /usr/local/src

... いろいろディレクトリのADDとかやっているところ

RUN apk update \
  && apk add --update --no-cache \
    git \
    build-base \
    curl \
    tzdata \
    xz-dev \
    mariadb-client \
    mariadb-dev \
    mariadb-connector-c \
    libc6-compat \
    libssl1.1 \
  && rm -rf /var/lib/apt/lists/* \
  && gem update --system \
  && gem install bundler \
  && RAILS_ENV=$RAILS_ENV CFLAGS="-Wno-cast-function-type" BUNDLE_FORCE_RUBY_PLATFORM=1 bundle install --deployment

EXPOSE 3000

ld-linux-x86-64.so.2はlibc6-compatに入っているもので、apk addしているやつに含めている。

pkgs.alpinelinux.org

配置場所こそlibではなくlib64だが、64bit向けビルドするとシステム的に自動判定されるはず(´・ω・`)


考えても何もわからなかったので、冒頭のリンクで紹介されていた https://hub.docker.com/r/frolvlad/alpine-glibc/dockerfile を試すことに。 ただ、これをDockerfireに適用するのかなり大掛かりな気がして、このdockerfileの中で使われている以下の導入をそのまま実行。

github.com


検証なのでなるべくミニマムでな。これ通りやればすんなりdocker-compose build --no-cache nameで、イメージビルド自体は通った。

docker-compose runでコンテナの中に入り、まずは手動で実行してbundle install。 特に問題なくGemは入る。その後、consoleなりmigrationを実行すると以下のようなエラーが発生してしまう。

/usr/local/src # RAILS_ENV=development bundle exec rails db:migrate
/usr/local/bundle/gems/google-protobuf-3.9.2-x86_64-linux/lib/google/protobuf/any_pb.rb:17: [BUG] Segmentation fault at 0x0000000000019266
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux-musl]

セグフォをくらう(´・ω・`)うーん....


セグフォの情報を元に調査すると、似たような症状を食らっている人が報告しているIssueを見つけた。

github.com

これを一通り読んでいった結果、結論、これで問題が解消した。

Segmentation Fault (Segfault) on the ruby gem · Issue #4460 · protocolbuffers/protobuf · GitHub

gem "grpc", "1.21.0", platforms: ["ruby"]
gem "google-protobuf", "3.8.0", platforms: ["ruby"]


ただ、確かに問題は解決するんだが、原因が全然わからず気持ち悪い(´・ω・`)で、いろいろ探した結果、以下に行き着いた。

github.com

I did a bit of digging and found that it was due to alpine gcc not being able to compile boringssl library due to function type cast error.

alpineのgccだと、boringsslのビルド時にキャストエラーで落ちてしまうらしい。なるほど。


ここで重要なのはおそらくplatforms: ["ruby"]
このオプションを指定することで、強制的にCRuby (MRI)としてビルドするように指定している。そうするとalpine向けでないビルドになるので、Alpineのgcc起因の問題は回避できるのだろうと理解しました。