【MySQL】Unknown MySQL server host 'db' (-2)の対処法【Docker】

##はじめに
Docker×MySQL×RailsAPI×Next.jsでポートフォリオ用の環境構築中に出現したエラー。
一日半みっちり悩んでいろんな方法を試したので、ここに戦いの記録を書き記す。
##環境
Docker:version3
MySQL:8.0
##状況
DockerからRailsのサーバーを立ち上げようとコンテナを起動し、````docker-compose run api rails db:create````すると、下記エラーでデータベースが作成されない。

````bash:ターミナル
my_app $ docker-compose run api rails db:create
Starting database ... done
Creating unknown_music_api_run ... done
Unknown MySQL server host 'db' (-2)
Couldn't create 'api_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 `<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 `<top (required)>'
Tasks: TOP => db:create
(See full trace by running task with --trace)
ERROR: 1
unknown_music $ docker-compose build
ERROR: yaml.scanner.ScannerError: mapping values are not allowed here
  in "./docker-compose.yml", line 22, column 16
unknown_music $ docker-compose build
ERROR: yaml.scanner.ScannerError: mapping values are not allowed here
  in "./docker-compose.yml", line 22, column 18

````

とりあえずエラー文を検索して上から試すローラー作戦実行。

##ローラー作戦

###１）DockerとMySQLのコネクト確認
どうやらDocker-compose.ymlのserver名とRailsのdatabase.ymlのhost名が同じじゃないと正常に繋がらないみたいなのでそこを確認。

````docker:docker-compose.yml

version: "3"

services:
  db: #database.ymlのhostと同じにする必要がある
    container_name: database
    image: mysql:8.0
    command: ["--character-set-server=utf8mb4",  "--collation-server=utf8mb4_unicode_ci", "--default-authentication-plugin=mysql_native_password"]
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: api_development
      MYSQL_USER: root
      MYSQL_PASSWORD: password

      TZ: Asia/Tokyo
    ports:
      - 3308:3306
    volumes:
      - ./back/database/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./back/database/data:/var/lib/mysql
      - ./back/database/sql:/docker-entrypoint-initdb.d
...下記省略

````

````ruby:database.yml

default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password
  host: db #ここをserver名と一致させる。

````

、、、どうやら問題はないらしい

###２）Dockerイメージ全削除
Dockerの古いイメージが残ってしまい、そちらを参照し続けてしまったことでエラーが起きるのでは？と言う記事を発見し試してみる。
このアプリの構築自体3回目くらい（作っては消してをくりかえした）なのでそれじゃないか！？と思い実行

````bash:ターミナル

$ docker stop $(docker ps -q)
$ docker rm $(docker ps -aq)
$ docker rmi $(docker images -q)

````

した後に

````bash:ターミナル

$ docker-compose build # コンテナをビルド
$ docker-compose up # コンテナの一斉起動

````

からの

````bash:ターミナル

$ docker-compose run web rails db:create

````

が、うまくいかず、、、

###３）Docker-compose.yml編集
これをVolumesに足したら上手く行ったよ！との記事を発見し実行。

````bash:ターミナル

 volumes:
      - ./tmp/db:/var/lib/mysql/data → ここの部分を足す
 
````

が、ダメ。

###４）削除系コマンド強化版
溜まっていく不要なコンテナやイメージを全消しする削除コマンドでコンテナを綺麗にしてみる。


````bash:コマンド

docker system prune --force --volumes

````
が、結果は変わらず。
他にもこまごました変更を試しまくり、一日目終了。
二日目は朝からPC再起動してみたり、Dockerコンテナを削除したり、MySQLを再インストールしたりして、
エラー検索のGoogle画面は、3ページまで踏んだリンクで色が変わり、こりゃいよいよ分からんぞ、、、と諦めムード。
ちょっと昼寝してから、もう脳死エラー文ローラー検索攻撃にたよらずに自分でエラーを理解する決意を固める←遅い
とりあえず問題の切り分けをしてみよう。
###５）MySQLのroot権限のパスワード
問題はDockerなのかMySQLなのか。
コンテナを見てみると、、、
どうやら立ち上がってないらしい。

````bash:ターミナル

unknown_music $ docker-compose ps
  Name                Command               State            Ports         
---------------------------------------------------------------------------
back       rails server -b 0.0.0.0          Up       0.0.0.0:3000->3000/tcp
database   docker-entrypoint.sh --cha ...   Exit 1                         
web        docker-entrypoint.sh yarn dev    Up       0.0.0.0:4001->3000/tcp

````

と言うことは、エラーの原因はMySQLではなくDockerか？と思い、DockerDesktopから該当コンテナのエラーlogを読む。
すると、````[ERROR] [Entrypoint]: Database is uninitialized and password option is not specified````と言う所で処理が止まっているではないか！！
これはつまり、MySQLのrootパスワードが設定されてない時に、```` MYSQL_ALLOW_EMPTY_PASSWORD: "yes"````を````docker-compose.yml````に記載することで````MYSQL_ROOT_PASSWORD````を空白にできると言うもの。
そうかMySQLを最インストールした時にrootのパスワード空にしたな、、、と思い、
このヒントを得て、編集した````docker-compose.yml````がこちら。

````docker:docker-compose.yml

version: "3"

services:
  db: #database.ymlのhostと同じにする必要がある
    container_name: database
    image: mysql:8.0
    command: ["--character-set-server=utf8mb4",  "--collation-server=utf8mb4_unicode_ci", "--default-authentication-plugin=mysql_native_password"]
    environment:
      MYSQL_ROOT_PASSWORD: #ここが空白
      MYSQL_DATABASE: api_development
      MYSQL_USER: root
      MYSQL_PASSWORD: password
      MYSQL_ALLOW_EMPTY_PASSWORD: "yes" #これ追加
      TZ: Asia/Tokyo
    ports:
      - 3308:3306
    volumes:
      - ./back/database/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./back/database/data:/var/lib/mysql
      - ./back/database/sql:/docker-entrypoint-initdb.d

  ...以下省略

````
これで````build````して````up````して````db:create````すると、、、
![スクリーンショット 2021-04-02 14.27.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076062/429d347b-abac-44b3-7b8e-e5eea2c09bf8.png)

やっったあああああああああああああああああ

##総括
やっぱり脳死でエラー文検索して上から試すのはあんまり良く無いなと学びました。
便利な世の中で優秀な先人達が書き記した知へ一瞬でアクセスできることで自分で考えることを放棄してはいけないな、と。
やはり自分で考え、問題を切り分け仮説を立て検証し、実行していくと言うプロセスが最も大事なんだと痛感した次第であります。
さあアプリ作ろ。