M1 MacでDocker＋Rails+Mysqlの環境構築ができるまで

M1 MacでDocker（プレビュー版）＋Rails＋Mysqlの環境構築に試行錯誤した話です。
正式版がでれば問題ないでしょうし、単に試行錯誤しただけなので誰の役にも立たないかもしれないですが、自戒の念をこめた備忘録として。。
初学者のためいたらない点が多々あるかと思いますが、間違ってる点などありましたらご教示ください。


# あらすじ

初学者の"ワタシ"が、M1 MacでDocker（Preview版）を使い
[こちら](https://www.youtube.com/watch?v=ltDdZAJli8c)に倣ってRails＋Mysqlの環境構築を試みる。

しかし、Mysqlが接続できない旨のエラーが発生。
偉大な先人の方々の記事をもとにあれこれ試すもうまくいかない。

白髪が3本増えたところで、最後、最後にもう一度だけ、、と
改めて「m1mac rails docker」でググったところ
[こちら](https://omathin.com/2021/01/16/m1-mac-dockercompose-rails/)の神記事に出会い、無事"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)
```

```docker-compose.yml
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
```

```database.yml
#該当箇所の抜粋です

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）](https://qiita.com/nagisawa_mamoru/items/3f1edeb2febe62622fae)

```docker-compose.yml
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://qiita.com/tetsuro_skiing/items/b380223c2611d392620a)
・https://github.com/docker/for-mac/issues/5142

```docker-compose.yml
  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 についてまとめた](https://qiita.com/at_1016/items/33186523cfc20fb58675)）
- Linux AIOとは？
　A = Asynchronous（非同期）、　IO = Input/Output （入出力） 

「Linuxのデータ非同期出入力係さんは、指定したMysqlのプラットフォームはサポートしてないよ」ということかな。
指定したDigest IDが違っていたのか、、
ググってもめぼしい解決策が見つからず挫折。。



## その3：dbのプラットフォームの指定を追記する
###参考
・https://stackoverflow.com/questions/65456814/docker-apple-silicon-m1-preview-mysql-no-matching-manifest-for-linux-arm64-v8

```docker-compose.yml
  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と変わらず。。


#考察

あらすじに書いたとおり、[こちらのお手本](https://omathin.com/2021/01/16/m1-mac-dockercompose-rails/)の通りに進めたところうまく環境構築ができたわけですが、
では何が違ったのか？というところを明らかにしていきたいと思います。

とにもかくにも、コンテナのステータスがずっっっとExit 1のまま。

お手本と照らし合わせていってどの段階でステータスがUpになるか見てみました。

##①イメージ名をお手本と同じに

```
image: mysql@sha256:dce31fcdd15aaedb5591aa89f19ec37cb79981af46511781fa41287d88ed0abd
```
#####結果　→変わらず　
これだけではやはりダメか。。。


##②Mysqlの設定ファイルの作成
```docker-compose.yml
  db:
    volumes:
      - ./src/db/mysql_data:/var/lib/mysql
      - ./mysql-confd:/etc/mysql/conf.d
```
```mysql-confd/default_authentication.cnf
[db]
default_authentication_plugin= mysql_native_password
```
#####結果　→変わらず　
ここが肝だと思ったけど・・・これだけではダメっぽい。

##③ttyとstdin_openをtrueに
```docker-compose.yml
  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の設定を変える（名前付きボリュームにする）
```docker-compose.yml
  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 がよくわからないから調べた](https://qiita.com/aki_55p/items/63c47214cab7bcb027e0)）

ちなみに今回の場合、①④の2点ができていればとコンテナ起動はできました。
が、②をしていないと、テーブル作成はやはりエラーになってしまったので、
やるべきこととしては①②④が必須なのかな、というところです。

と書いたところで、あれこれ消してビルドして、を繰り返しすぎたのか
何してもエラーでるようになってしまいました。。
やっぱりプレビュー版はMysqlのイメージには対応できてないってことでしょうか。。


#結論
- ちゃんと動くイメージ名で指定しないといけなかった
- 名前付きボリュームを使ってストレージ領域を確保する必要があった

反省点としては、出てきたエラー文を特に自分で読み込みもせず、
機械的にググってばかりだったということ。
ググって出てこなかったらハイ終わりー、ではダメですよね。。

あとはエラー対処しつつ、ちゃんと「どんなエラーにどう対処したのか」を並行してまとめておくべきだったなと。
どこかに書き出してれば、ちゃんと思考が働くし脳みそが整理されるし、
最終的に誰かに質問したくなってもそれを元に聞けるし。

以後気をつけます！！


なにはともあれ、Docker Desktop (for apple silicon)の正式版が1日も早くリリースされますように。