Docker(Mac)でgRPC FUSE有効時にMySQL8コンテナが起動しない問題について調査報告と解決策

# はじめに

Docker環境でRailsアプリケーションを開発する際にDocker Desktop for MacのgRPC FUSEを有効にした状態でコンテナを起動すると、MySQL8のコンテナが起動しない問題が発生した。

こんな感じ

```terminal
db_1     | 2021-03-05T17:42:39.341701Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
db_1     | 2021-03-05T17:42:40.003650Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
db_1     | 2021-03-05T17:42:40.011792Z 1 [ERROR] [MY-011087] [Server] Different lower_case_table_names settings for server ('2') and data dictionary ('0').
db_1     | 2021-03-05T17:42:40.012090Z 0 [ERROR] [MY-010020] [Server] Data Dictionary initialization failed.
db_1     | 2021-03-05T17:42:40.012378Z 0 [ERROR] [MY-010119] [Server] Aborting
db_1     | 2021-03-05T17:42:40.618413Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.23)  MySQL Community Server - GPL.
```


この問題はDocker 2.4.0から報告されている有名な問題らしく、gRPC FUSEをオフにすることで改善できる問題とのことだった。
参考：[Mysql not starting in a docker container on MacOS after docker update](https://stackoverflow.com/questions/64146845/mysql-not-starting-in-a-docker-container-on-macos-after-docker-update)

しかし、(本来ここについても調査すべきなのかもしれないがw)gRPC FUSEをオフにすることで、docker-composeを起動中にアプリケーションに編集を加えるとコンテナやアプリケーションがフリーズして再起動を必要とする…ということが起きてしまったため、
なんとかgRPC FUSEを有効にした状態でMySQL8コンテナを起動することはできないか、自分なりに調査をしてみました。
<br>
<br>
あくまでも「私はこのように調査したよ、このように対処したよ」という報告のような内容の記事ですので、ここに書いてある内容が正しいノウハウ、知識という認識で読まれるのはオススメしません。
この記事をきっかけに正しい知恵をいただいたり、もしくはこの問題についての議論が進むことを望みます。

# 実行環境

- MacBook Pro 16inch 2019
- macOS 11.2.2

- Docker Desktop for Mac 3.1.0  **※gRPC FUSEを有効にする**

**docker-composeファイルの設定**

```docker-compose.yml
  db:
    image: mysql:8.0.23
    command: mysqld --default-authentication-plugin=mysql_native_password
    volumes:
      - ./mysql/mysql:/var/lib/mysql
```


# いろいろわかったこと(原因は不明)

## 再ビルドしても起動しなかった

再度ビルドをしてみてクリーンな状態で起動してみてはどうか、と考えたが改善しなかった。
--no-cacheオプションも試しましたが関係ありませんでした。


## 別のログインユーザーは正常に起動した

私のMacBookにはプライベート用とそれ以外用とでユーザーアカウントをわけている。
今回、テストしてみたところ、同じRailsアプリケーション、同じdokker-composeファイルにもかかわらず、プライベート用のユーザーアカウントでは問題なくMySQL8コンテナを起動することができた。
インストールしているアプリケーションや開発環境の内容はほぼいっしょ(のはず)のため、もう一方のユーザーアカウントで起動しなかった理由はわからず…

## インターン生のPCでも正常に起動した

私の勤務している会社で働いてくれているインターン生のMacBookでも正常に起動していた。
こちらのMacBookは最近使い始められたばかりで、特に設定やアプリのインストールがされているわけではないので、それが原因で起動した説…はあるかもしれない。。。

## Dockerのバージョンを上げてみたが改善せず…

無駄でした…なお、バージョンを下げるのはなんだか気分が乗らなかったのでやめた。

## docker-compose run db bashでコンテナに入ってみた => データベースが読み込まれていなかった

gRPC FUSEをオフの状態でMySQLコンテナに入り、MySQLを起動すると、
RailsのActiveRecordで作成したデータベーステーブルをshow databases;で見つけることができた。

しかし、gRPC FUSEを有効にしてから同様の処理をすると…そもそもMySQLにすらログインさせてもらえなかった。
つまり、データベースが読み込まれていない、ということだ。

なるほど…ということは、MySQLのデータを永続化させるために設定しているVolumesが怪しいのでは…？

## MySQLコンテナのvolumesの記述を削除すると…起動した

MySQLデータを永続化させるためのvolumes設定を削除してみたところ、、、ついに、MySQLコンテナが正常に動作してくれた。
しかし、このままでは毎回コンテナ起動時にデータベースを作成しなければいけない。うーん、どうしたらいいものか。

# そして見つけた、自分なりの改善策

## MySQLのデータのマウント先を名前付きVolumesに設定 => 起動した！

Volumesが怪しいと思いいろいろ調べてみたところ、こちらの記事を見つけることができた。

[Docker上のMySQLのデータをVolumeでホストのディレクトリにマウントすると権限周りで面倒なことになる](https://qiita.com/ysd_marrrr/items/e8a50c43cff87951385c)
[Dockerのvolumeでpermission deniedが発生した場合の解決法](https://tech-blog.rakus.co.jp/entry/20200826/docker)

Macでは発生しない問題(？)についての記事ではあったのですが、この記事を見て名前付きVolumesを設定したらどうなるだろう、と思った。

docker-composeファイルの設定のうち、volumesの設定を以下のように変更してみました。

```docker-compose.yml
  db:
    image: mysql:8.0.23
    command: mysqld --default-authentication-plugin=mysql_native_password
    volumes:
      - mysql_data:/var/lib/mysql
volumes:
  mysql_data:  # 名前付きVolumesを定義
```

すると…

<br>
<br>

**動いた！！！**(´；ω；｀)

<br>
<br>

データもしっかり永続化できているので、docker-compose downしてから再度コンテナを起動させても、問題なくデータベースを読み込むことができた。
改めて思うと、永続化データをプロジェクトディレクトリ内にマウントする必要性も特に感じないので、名前付きVolumesに設定で全然問題ないんですよね。次からこのやり方で統一していこうと思います。
<br>
<br>
。。。しかし、今回MySQLコンテナをgRPC FUSE有効時にも正常動作させるのにかなり苦労したが、名前付きVolumesを使わずとも正常に動作する環境があるのも事実…なので完全な問題解決、理解には至っていないのだ。。。

# おわりに

とりあえずの対処法は発見できたものの、まだこの問題の根本的な解消には至っていないと考えています。Dockerに対しての理解が浅いために、この程度までの調査、分析しかできませんでした。
今年に入ってこの問題に関する記事が新規で上がっていないところを見ると、皆さんすでに解決済み？なのかもしれませんが、もしかしたら今も困っている方がいらっしゃるかもしれません。

もし、この問題の原因、解決法に詳しい方がいらっしゃいましたらコメント欄でご教授いただけますと幸いです。
この記事が、DockerのgRPC FUSE問題に苦しむ方の解決のきっかけにつながることを願います。