はじめに
前回書いた記事「既存RailsアプリをDocker化する手順」でDocker環境を構築する過程で、
yarn install
時でM1チップ特有のエラーが発生しました。
今回は備忘録も兼ねエラーについて簡単にまとめていきたいと思います。
※下記記事ではエラーが発生しないよう対応済みです。
開発環境
下記開発環境にてDocker化を行いました。
- CPU: Apple M1
- OS: MacOS Ventura バージョン13.3.1
各種設定
Docker化するにあたり、使用したバージョンは以下の通りです。
- ruby: 3.0.2
- rails: 6.0.3
- node: 15.0.1
- postgresql: 12.0
また、Dockerfileとdocker-compose.ymlの設定は以下の通りです。
FROM node:15.0.1 as node
FROM ruby:3.0.2
COPY --from=node /opt/yarn-* /opt/yarn
COPY --from=node /usr/local/bin/node /usr/local/bin/
COPY --from=node /usr/local/lib/node_modules/ /usr/local/lib/node_modules/
RUN ln -fs /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm \
&& ln -fs /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npx \
&& ln -fs /usr/local/lib/node /usr/local/bin/nodejs \
&& ln -fs /opt/yarn/bin/yarn /usr/local/bin/yarn \
&& ln -fs /opt/yarn/bin/yarn /usr/local/bin/yarnpkg
RUN apt-get update && apt-get install -y \
build-essential \
libpq-dev \
postgresql-client
RUN mkdir /myapp
WORKDIR /myapp
COPY package.json /myapp/package.json
COPY yarn.lock /myapp/yarn.lock
RUN yarn install
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp
version: '3'
services:
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0' &&
ports:
- '3000:3000'
volumes:
- .:/myapp
environment:
- 'DATABASE_PASSWORD=postgres'
tty: true
stdin_open: true
depends_on:
- 'db'
db:
image: postgres:12.0
environment:
- POSTGRES_PASSWORD=password
エラー内容
上記Dokcerfileとdocker-compose.ymlの設定で、docker-compose build
を実行すると、
下記の通り、yarn install
でエラーが発生します。
内容を見るに、/lib/ld-linux-armhf.so.3
というファイルまたはディレクトリがないと
言っている模様。
=> ERROR [stage-1 11/15] RUN yarn install 0.2s
------
> [stage-1 11/15] RUN yarn install:
#0 0.165 qemu-arm: Could not open '/lib/ld-linux-armhf.so.3': No such file or directory
------
failed to solve: process "/bin/sh -c yarn install" did not complete successfully: exit code: 255
解決方法
エラー内容を調べていると、どうやらアーキテクチャに問題があることが判明しました。
Dockerfileで指定した、node:15.0.1
をDocker hubで調べてみると、
下図赤枠部分の通り、M1のアーキテクチャであるlinux/arm/v8
には対応していない模様。
よって、nodeのバージョンを以下の通り、linux/arm/v8
に対応したバージョンを選択し、
再度docker-compose build
を実行します。
(※最新のバージョンを選択すると別のエラーが発生したので、今回はVer.16.13を選択)
- FROM node:15.0.1 as node
+ FROM node:16.13 as node
どうやら、無事にインストールできた模様。
=> [stage-1 2/15] COPY --from=node /opt/yarn-* /opt/yarn 0.0s
=> [stage-1 3/15] COPY --from=node /usr/local/bin/node /usr/local/bin/ 0.1s
=> [stage-1 4/15] COPY --from=node /usr/local/lib/node_modules/ /usr/lo 0.2s
=> [stage-1 5/15] RUN ln -fs /usr/local/lib/node_modules/npm/bin/npm-cl 0.2s
=> [stage-1 6/15] RUN apt-get update && apt-get install -y build-es 6.2s
=> [stage-1 7/15] RUN mkdir /myapp 0.2s
=> [stage-1 8/15] WORKDIR /myapp 0.0s
=> [stage-1 9/15] COPY package.json /myapp/package.json 0.0s
=> [stage-1 10/15] COPY yarn.lock /myapp/yarn.lock 0.0s
=> [stage-1 11/15] RUN yarn install 19.5s
=> [stage-1 12/15] COPY Gemfile /myapp/Gemfile 0.0s
=> [stage-1 13/15] COPY Gemfile.lock /myapp/Gemfile.lock 0.0s
=> [stage-1 14/15] RUN bundle install 60.9s
=> [stage-1 15/15] COPY . /myapp 2.0s
=> exporting to image 2.2s
=> => exporting layers 2.2s
あとは、docker-compose run web rails db:create db:migrate
と
docker-compose up
を実行することで、railsアプリを無事に起動することができました🎉
参考
アーキテクチャをlinux/arm/v8
に対応したものに変更する方法以外に、
platform
を指定する方法でもエラーを解消することができます。
以下の通り、docker-compose.yml
にplatform: linux/amd64
を追記し、
docker-compose build
を実行します。
platform: linux/amd64
によって、アーキテクチャをamd64に設定しています。
services:
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0' &&
ports:
- '3000:3000'
volumes:
- .:/myapp
+ platform: linux/amd64
environment:
- 'DATABASE_PASSWORD=postgres'
tty: true
stdin_open: true
depends_on:
- 'db'
10分〜15分ほど待つと無事ビルドが完了します。
(bundle installが長く、自分は途中でインストールが失敗しているものと勘違いしていました)
=> [stage-1 2/15] COPY --from=node /opt/yarn-* /opt/yarn 0.0s
=> [stage-1 3/15] COPY --from=node /usr/local/bin/node /usr/local/bin/ 0.1s
=> [stage-1 4/15] COPY --from=node /usr/local/lib/node_modules/ /usr/lo 0.2s
=> [stage-1 5/15] RUN ln -fs /usr/local/lib/node_modules/npm/bin/npm-cl 0.3s
=> [stage-1 6/15] RUN apt-get update && apt-get install -y build-e 36.8s
=> [stage-1 7/15] RUN mkdir /myapp 0.3s
=> [stage-1 8/15] WORKDIR /myapp 0.0s
=> [stage-1 9/15] COPY package.json /myapp/package.json 0.0s
=> [stage-1 10/15] COPY yarn.lock /myapp/yarn.lock 0.0s
=> [stage-1 11/15] RUN yarn install 71.2s
=> [stage-1 12/15] COPY Gemfile /myapp/Gemfile 0.0s
=> [stage-1 13/15] COPY Gemfile.lock /myapp/Gemfile.lock 0.0s
=> [stage-1 14/15] RUN bundle install 565.5s
=> [stage-1 15/15] COPY . /myapp 3.3s
=> exporting to image 2.8s
=> => exporting layers 2.8s
このままdocker-compose run web rails db:create db:migrate
を実行すると、
下記エラーが発生するため、config/environment/development.rb
を
以下の通り編集します。
rails aborted!
Errno::ENOSYS: Function not implemented - Failed to initialize inotify
- config.file_watcher = ActiveSupport::EventedFileUpdateChecker
+ config.file_watcher = ActiveSupport::FileUpdateChecker
そして、docker-compose run web rails db:create db:migrate
と
docker-compose up
を実行することで、railsアプリを起動することができます。
まとめ
最後に本記事のまとめです。
- M1MacでDockerを使用する際は、使用するパッケージが
linux/arm/v8
に対応しているか確認する - アーキテクチャを
linux/amd64
指定することで、エラーを回避する方法もあるが、
最適化されているlinux/arm/v8
の方が動作が速い
(特にインストールの時間はかなり違います)
以上となります。最後まで記事を読んでいただきありがとうございます。