どうもてぃ。お久しぶりです。
今日も解決記事です。
環境
- ruby 3.0.0 (alpine image)
- PostgreSQL v12 (alpine image)
- rails 6.1.4
- Docker version 20.10.2, build 20.10.2-0ubuntu1~18.04.2
- docker-compose version 1.27.4, build 40524192
% cat /ext/lsb-release DISTRIB_ID=LinuxMint DISTRIB_RELEASE=19.3 DISTRIB_CODENAME=tricia DISTRIB_DESCRIPTION="Linux Mint 19.3 Tricia"
一応Dockerfile
FROM ruby:3.0.0-alpine ENV RUNTIME_PACKAGES="linux-headers build-base libxml2-dev libxslt-dev make gcc libc-dev nodejs yarn tzdata g++ postgresql-dev postgresql git openssl less curl unzip" \ CHROME_PACKAGES="chromium-chromedriver zlib-dev chromium xvfb wait4ports xorg-server dbus ttf-freefont mesa-dri-swrast udev" \ DELETE_PACKAGES="build-packages libxml2-dev make gcc curl-dev libc-dev g++ curl unzip" \ BUILD_PACKAGES="build-base curl-dev" \ APP_ROOT="/myapp" \ LANG=C.UTF-8 \ TZ=Asia/Tokyo RUN apk update && \ apk upgrade && \ apk add --no-cache ${RUNTIME_PACKAGES} && \ apk add --no-cache ${CHROME_PACKAGES} && \ apk add --virtual build-packages --no-cache ${BUILD_PACKAGES} && \ gem install rails -v '6.1.4' && \ gem install bundler WORKDIR /tmp COPY Gemfile* ./ RUN curl -O -L https://noto-website-2.storage.googleapis.com/pkgs/NotoSansCJKjp-hinted.zip && \ unzip NotoSansCJKjp-hinted.zip -d . && \ mkdir -p /usr/share/fonts/noto && \ cp ./*.otf /usr/share/fonts/noto/ && \ chmod 644 /usr/share/fonts/noto/*.otf && \ fc-cache -fv RUN bundle install -j4 && \ bundle clean --force && \ apk del ${DELETE_PACKAGES} ${BUILD_PACKAGES} && \ cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \ rm -rf /usr/local/share/.cache/* /var/cache/* /tmp/* WORKDIR $APP_ROOT COPY . ${APP_ROOT}/ CMD ["rails", "server", "-b", "0.0.0.0"]
fontを入れてるのはスクレイピング用です。
他は何の変哲もない(自分では)しっかりと作り込んだ(つもりでいた)愛を全力で注ぎ込んだDockerfileです。
やりたかったこと
上記2点。
今まで別のプロジェクトでも何の問題もなく動いていたので、Dockerfile
とdocker-compose.yml
をrails apiモード用にちょっといじってビルドしました。
事件はおこった
その1: gemのコンパイルでgccとmakeが必要だった
まあ、よくあるやつ。
これはDockerfileのDELETE_PACKAGEから除外すれば直りました。
修正したDockerfileが以下。
FROM ruby:3.0.0-alpine # don't delete make and gcc ENV RUNTIME_PACKAGES="linux-headers build-base libxml2-dev libxslt-dev make gcc libc-dev nodejs yarn tzdata g++ postgresql-dev postgresql git openssl less curl unzip" \ CHROME_PACKAGES="chromium-chromedriver zlib-dev chromium xvfb wait4ports xorg-server dbus ttf-freefont mesa-dri-swrast udev" \ DELETE_PACKAGES="build-packages libxml2-dev curl-dev libc-dev g++ curl unzip" \ BUILD_PACKAGES="build-base curl-dev" \ APP_ROOT="/myapp" \ LANG=C.UTF-8 \ TZ=Asia/Tokyo RUN apk update && \ apk upgrade && \ apk add --no-cache ${RUNTIME_PACKAGES} && \ apk add --no-cache ${CHROME_PACKAGES} && \ apk add --virtual build-packages --no-cache ${BUILD_PACKAGES} && \ gem install rails -v '6.1.4' && \ gem install bundler WORKDIR /tmp COPY Gemfile* ./ RUN curl -O -L https://noto-website-2.storage.googleapis.com/pkgs/NotoSansCJKjp-hinted.zip && \ unzip NotoSansCJKjp-hinted.zip -d . && \ mkdir -p /usr/share/fonts/noto && \ cp ./*.otf /usr/share/fonts/noto/ && \ chmod 644 /usr/share/fonts/noto/*.otf && \ fc-cache -fv RUN bundle install -j4 && \ bundle clean --force && \ apk del ${DELETE_PACKAGES} ${BUILD_PACKAGES} && \ cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \ rm -rf /usr/local/share/.cache/* /var/cache/* /tmp/* WORKDIR $APP_ROOT COPY . ${APP_ROOT}/ CMD ["rails", "server", "-b", "0.0.0.0"]
その2: msgpackのインストールでコケる
まずはエラーメッセージ。
Gem::Ext::BuildError: ERROR: Failed to build gem native extension. current directory: /usr/local/bundle/gems/msgpack-1.4.2/ext/msgpack /usr/local/bin/ruby -I /usr/local/lib/ruby/3.0.0 -r ./siteconf20210630-1-7hbtci.rb extconf.rb checking for ruby/st.h... *** extconf.rb failed *** Could not create Makefile due to some reason, probably lack of necessary libraries and/or headers. Check the mkmf.log file for more details. You may need configuration options. Provided configuration options: --with-opt-dir --without-opt-dir --with-opt-include --without-opt-include=${opt-dir}/include --with-opt-lib --without-opt-lib=${opt-dir}/lib --with-make-prog --without-make-prog --srcdir=. --curdir --ruby=/usr/local/bin/$(RUBY_BASE_NAME) --with-ruby-dir --without-ruby-dir --with-ruby-include --without-ruby-include=${ruby-dir}/include --with-ruby-lib --without-ruby-lib=${ruby-dir}/lib /usr/local/lib/ruby/3.0.0/mkmf.rb:471:in `try_do': The compiler failed to generate an executable file. (RuntimeError) You have to install development tools first. from /usr/local/lib/ruby/3.0.0/mkmf.rb:613:in `try_cpp' from /usr/local/lib/ruby/3.0.0/mkmf.rb:1124:in `block in have_header' from /usr/local/lib/ruby/3.0.0/mkmf.rb:971:in `block in checking_for' from /usr/local/lib/ruby/3.0.0/mkmf.rb:361:in `block (2 levels) in postpone' from /usr/local/lib/ruby/3.0.0/mkmf.rb:331:in `open' from /usr/local/lib/ruby/3.0.0/mkmf.rb:361:in `block in postpone' from /usr/local/lib/ruby/3.0.0/mkmf.rb:331:in `open' from /usr/local/lib/ruby/3.0.0/mkmf.rb:357:in `postpone' from /usr/local/lib/ruby/3.0.0/mkmf.rb:970:in `checking_for' from /usr/local/lib/ruby/3.0.0/mkmf.rb:1123:in `have_header' from extconf.rb:3:in `<main>' To see why this extension failed to compile, please check the mkmf.log which can be found here: /usr/local/bundle/extensions/x86_64-linux-musl/3.0.0/msgpack-1.4.2/mkmf.log extconf failed, exit code 1 Gem files will remain installed in /usr/local/bundle/gems/msgpack-1.4.2 for inspection. Results logged to /usr/local/bundle/extensions/x86_64-linux-musl/3.0.0/msgpack-1.4.2/gem_make.out An error occurred while installing msgpack (1.4.2), and Bundler cannot continue. Make sure that `gem install msgpack -v '1.4.2' --source 'https://rubygems.org/'` succeeds before bundling. In Gemfile: bootsnap was resolved to 1.7.5, which depends on msgpack
例のごとく最後に書いてる gem install msgpack -v '1.4.2' --source 'https://rubygems.org/'
を実行してもダメ。
なのでmkmf.logを確認(docker containerに入ってから実行してます)。
/myapp # cat /usr/local/bundle/extensions/x86_64-linux-musl/3.0.0/msgpack-1.4.2/mkmf.log "gcc -o conftest -I/usr/local/include/ruby-3.0.0/x86_64-linux-musl -I/usr/local/include/ruby-3.0.0/ruby/backward -I/usr/local/include/ruby-3.0.0 -I. -O3 -ggdb3 -Wall -Wextra -Wdeprecated-declarations -Wduplicated-cond -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wwrite-strings -Wimplicit-fallthrough=0 -Wmissing-noreturn -Wno-cast-function-type -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-packed-bitfield-compat -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wsuggest-attribute=format -Wsuggest-attribute=noreturn -Wunused-variable -fPIC conftest.c -L. -L/usr/local/lib -Wl,-rpath,/usr/local/lib -L. -fstack-protector-strong -rdynamic -Wl,-export-dynamic -Wl,-rpath,/usr/local/lib -L/usr/local/lib -lruby -lm -lc" In file included from /usr/local/include/ruby-3.0.0/ruby/ruby.h:23, from /usr/local/include/ruby-3.0.0/ruby.h:38, from conftest.c:1: /usr/local/include/ruby-3.0.0/ruby/defines.h:16:10: fatal error: stdio.h: No such file or directory 16 | #include <stdio.h> | ^~~~~~~~~ compilation terminated. checked program was: /* begin */ 1: #include "ruby.h" 2: 3: int main(int argc, char **argv) 4: { 5: return !!argv[argc]; 6: } /* end */
あれー?gccを最後削除するパッケージ対象から外してるんすけど。意味わからん。
msgpack関連をめちゃくちゃ検索してましたが、もしかしたらOSに何かあったのかもと思い、「docker alpine gcc stdio.h~~~~」みたいな感じで検索したら原因発覚。
alpineのgccとlibc-devの依存関係が非推奨で無くなってしまったとのこと。
別の記事では(ちょっとリンク忘れちゃった)、代わりに musl-dev
入れたら最強になれるみたいなこと書いてました。
なので更に修正したDockerfileが以下。
FROM ruby:3.0.0-alpine # don't delete make and gcc ENV RUNTIME_PACKAGES="linux-headers build-base libxml2-dev libxslt-dev make gcc musl-dev nodejs yarn tzdata g++ postgresql-dev postgresql git openssl less curl unzip" \ CHROME_PACKAGES="chromium-chromedriver zlib-dev chromium xvfb wait4ports xorg-server dbus ttf-freefont mesa-dri-swrast udev" \ DELETE_PACKAGES="build-packages libxml2-dev curl-dev libc-dev g++ curl unzip" \ BUILD_PACKAGES="build-base curl-dev" \ APP_ROOT="/myapp" \ LANG=C.UTF-8 \ TZ=Asia/Tokyo RUN apk update && \ apk upgrade && \ apk add --no-cache ${RUNTIME_PACKAGES} && \ apk add --no-cache ${CHROME_PACKAGES} && \ apk add --virtual build-packages --no-cache ${BUILD_PACKAGES} && \ gem install rails -v '6.1.4' && \ gem install bundler WORKDIR /tmp COPY Gemfile* ./ RUN curl -O -L https://noto-website-2.storage.googleapis.com/pkgs/NotoSansCJKjp-hinted.zip && \ unzip NotoSansCJKjp-hinted.zip -d . && \ mkdir -p /usr/share/fonts/noto && \ cp ./*.otf /usr/share/fonts/noto/ && \ chmod 644 /usr/share/fonts/noto/*.otf && \ fc-cache -fv RUN bundle install -j4 && \ bundle clean --force && \ apk del ${DELETE_PACKAGES} ${BUILD_PACKAGES} && \ cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \ rm -rf /usr/local/share/.cache/* /var/cache/* /tmp/* WORKDIR $APP_ROOT COPY . ${APP_ROOT}/ CMD ["rails", "server", "-b", "0.0.0.0"]
libc-dev
を外してmusl-dev
を入れてます。
以上で無事ビルドとbundle installが通りましたとさ。
おわり
alpineイメージを使うメリットあまり感じてないので、slim-busterか普通のやつに変えようかなと模索中。
前見たときgithub actionで使うimageにalpineなかったからなー(もしかしたらもうあるかも)。
docker-compose v3.8のキャッチアップと一緒にプロジェクトのimage見直しやってみようと思います。
おつでした。