M1 MacでDocker(プレビュー版)+Rails+Mysqlの環境構築に試行錯誤した話です。
正式版がでれば問題ないでしょうし、単に試行錯誤しただけなので誰の役にも立たないかもしれないですが、自戒の念をこめた備忘録として。。
初学者のためいたらない点が多々あるかと思いますが、間違ってる点などありましたらご教示ください。
あらすじ
初学者の"ワタシ"が、M1 MacでDocker(Preview版)を使い
こちらに倣ってRails+Mysqlの環境構築を試みる。
しかし、Mysqlが接続できない旨のエラーが発生。
偉大な先人の方々の記事をもとにあれこれ試すもうまくいかない。
白髪が3本増えたところで、最後、最後にもう一度だけ、、と
改めて「m1mac rails docker」でググったところ
こちらの神記事に出会い、無事"Yaaayyyyy! I'm on Raaaaails!!!!!"となった、という話。とその考察です。
発生した問題・エラー、各ファイルの状態
Unknown MySQL server host 'db' (-2)
Couldn't create 'app_development' database. Please check your configuration.
rails aborted!
ActiveRecord::ConnectionNotEstablished: Unknown MySQL server host 'db' (-2)
/app/bin/rails:5:in `<top (required)>'
/app/bin/spring:10:in `block in <top (required)>'
/app/bin/spring:7:in `tap'
/app/bin/spring:7:in `<top (required)>'
Caused by:
Mysql2::Error::ConnectionError: Unknown MySQL server host 'db' (-2)
/app/bin/rails:5:in `<top (required)>'
/app/bin/spring:10:in `block in <top (required)>'
/app/bin/spring:7:in `tap'
/app/bin/spring:7:in `<top (required)>'
Tasks: TOP => db:create
(See full trace by running task with --trace)
version: '3'
services:
db:
image: mysql:8.0
command: --default-authentication-plugin=mysql_native_password
volumes:
- ./src/db/mysql_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: password
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- ./src:/app
ports:
- "3000:3000"
depends_on:
- db
#該当箇所の抜粋です
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password: password
host: db
自分で試したこと
その1:mysqlではなくMariaDBを使う
###参考
- https://stackoverflow.com/questions/65456814/docker-apple-silicon-m1-preview-mysql-no-matching-manifest-for-linux-arm64-v8
- Rails + mariadb on Dockerの環境構築(Docker for Mac)
version: '3'
services:
db:
image: mariadb:10.5
volumes:
- ./src/db/mysql_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: root
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- ./src:/app
ports:
- "3000:3000"
depends_on:
- db
volumes:
bundle:
mysql_data:
###結果
#####エラー文
変わらず。
#####ログ
[ERROR] mysqld: Got error 'Missing valid id at start of file. File is not a valid aria control file' when trying to use aria control file '/var/lib/mysql/aria_log_control'
[ERROR] Plugin 'Aria' init function returned error.
[ERROR] Plugin 'Aria' registration as a STORAGE ENGINE failed.
[ERROR] InnoDB: The Auto-extending innodb_system data file './ibdata1' is of a different size 317 pages than specified in the .cnf file: initial 768 pages, max 0 (relevant if non-zero) pages!
[ERROR] InnoDB: Plugin initialization aborted with error Generic error
[ERROR] Plugin 'InnoDB' init function returned error.
[ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
[Note] Plugin 'FEEDBACK' is disabled.
[ERROR] Could not open mysql.plugin table: "Unknown storage engine 'Aria'". Some plugins may be not loaded
[ERROR] Failed to initialize plugins.
[ERROR] Aborting
#####【知らなかったのでメモ】
- Ariaとは? MariaDBのストレージエンジン。
- aria_log_controlとは? Ariaのセットアップに必要な情報がのってるファイル。
どうやらaria_log_controlかそこに書いてあるIDが有効じゃない、というエラー。
ググってもめぼしい解決策に出会えず・・断念。
その2:mysqlのイメージIDを指定する
###参考
・M1 mac Docker preview版でmysqlを使う方法
・https://github.com/docker/for-mac/issues/5142
db:
image: mysql:5.7@sha256:b3b2703de646600b008cbb2de36b70b21e51e7e93a7fca450d2b08151658b2dd
command: --default-authentication-plugin=mysql_native_password
volumes:
- ./src/db/mysql_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: password
###結果
#####エラー文
変わらず。
#####ログ
[ERROR] InnoDB: Linux Native AIO interface is not supported on this platform. Please check your OS documentation and install appropriate binary of InnoDB.
[ERROR] 1030 Got error 175 from storage engine
[ERROR] Aborting
[ERROR] InnoDB: Log file ./ib_logfile1 is of different size 0 bytes than other log files 50331648 bytes!
[ERROR] InnoDB: Plugin initialization aborted with error Generic error
[ERROR] Plugin 'InnoDB' init function returned error.
[ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
[ERROR] Failed to initialize builtin plugins.
[ERROR] Aborting
#####【知らなかったのでメモ】
- InnoDBとは?
Mysqlのストレージエンジン。データベースの読み書きをしてくれる。(参考:MySQL についてまとめた) - Linux AIOとは?
A = Asynchronous(非同期)、 IO = Input/Output (入出力)
「Linuxのデータ非同期出入力係さんは、指定したMysqlのプラットフォームはサポートしてないよ」ということかな。
指定したDigest IDが違っていたのか、、
ググってもめぼしい解決策が見つからず挫折。。
その3:dbのプラットフォームの指定を追記する
db:
platform: linux/x86_64
image: mysql:8.0
command: --default-authentication-plugin=mysql_native_password
volumes:
- ./src/db/mysql_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: password
###結果
その2と変わらず。。
#考察
あらすじに書いたとおり、こちらのお手本の通りに進めたところうまく環境構築ができたわけですが、
では何が違ったのか?というところを明らかにしていきたいと思います。
とにもかくにも、コンテナのステータスがずっっっとExit 1のまま。
お手本と照らし合わせていってどの段階でステータスがUpになるか見てみました。
##①イメージ名をお手本と同じに
image: mysql@sha256:dce31fcdd15aaedb5591aa89f19ec37cb79981af46511781fa41287d88ed0abd
#####結果 →変わらず
これだけではやはりダメか。。。
##②Mysqlの設定ファイルの作成
db:
volumes:
- ./src/db/mysql_data:/var/lib/mysql
- ./mysql-confd:/etc/mysql/conf.d
[db]
default_authentication_plugin= mysql_native_password
#####結果 →変わらず
ここが肝だと思ったけど・・・これだけではダメっぽい。
##③ttyとstdin_openをtrueに
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- ./src:/app
ports:
- "3000:3000"
depends_on:
- db
tty: true #ココ
stdin_open: true #ココ
#####結果 →変わらず
dbに関しての記述じゃないからそりゃそう。
最終的になくてもコンテナ立ち上がりました。
#####【知らなかったのでメモ】
- stdin_openとは? コンテナの標準入力をオープンしたままにする。
- ttyとは? どうやらコンテナを起動させ続けるためのもの。
##④volumesの設定を変える(名前付きボリュームにする)
db:
image: mysql@sha256:dce31fcdd15aaedb5591aa89f19ec37cb79981af46511781fa41287d88ed0abd
command: --default-authentication-plugin=mysql_native_password
volumes:
- db-volume:/var/lib/mysql #ココと
- ./mysql-confd:/etc/mysql/conf.d
volumes: #ココ
db-volume: #ココ
#####結果 →これでようやくステータスがUPに変わりました!
振り返ってみるとログのエラー文の中に、なにやらストレージが足りてなさそうな文言が入ってました。。
このあたりの解決能力があれば、、反省です。
#####【知らなかったのでメモ】
- volumes: 名前付きボリューム。
(参考:Docker の Volume がよくわからないから調べた)
ちなみに今回の場合、①④の2点ができていればとコンテナ起動はできました。
が、②をしていないと、テーブル作成はやはりエラーになってしまったので、
やるべきこととしては①②④が必須なのかな、というところです。
と書いたところで、あれこれ消してビルドして、を繰り返しすぎたのか
何してもエラーでるようになってしまいました。。
やっぱりプレビュー版はMysqlのイメージには対応できてないってことでしょうか。。
#結論
- ちゃんと動くイメージ名で指定しないといけなかった
- 名前付きボリュームを使ってストレージ領域を確保する必要があった
反省点としては、出てきたエラー文を特に自分で読み込みもせず、
機械的にググってばかりだったということ。
ググって出てこなかったらハイ終わりー、ではダメですよね。。
あとはエラー対処しつつ、ちゃんと「どんなエラーにどう対処したのか」を並行してまとめておくべきだったなと。
どこかに書き出してれば、ちゃんと思考が働くし脳みそが整理されるし、
最終的に誰かに質問したくなってもそれを元に聞けるし。
以後気をつけます!!
なにはともあれ、Docker Desktop (for apple silicon)の正式版が1日も早くリリースされますように。