MySQL コンテナ起動時に止まったまま動かない現象の解消

# はじめに
PHP と MySQL の環境構築を行っていた際、`docker-compose up -d` でコンテナを作成し、動作させようとした。PHPのコンテナは正常に動いたが、MySQL のコンテナが build は正常にできたものの、動作がうまくいかなかった。  
以下は、 `docker-compose up -d` を実行した際にターミナルに表示された内容である。
```
[+] Building 0.0s (0/0)
[+] Running 2/0
 ✔ Container mysql-container  Running                                              0.0s 
    Container php-container    Starting     
```

# 環境
- OS: Windows10
- PHP: 7.3-apache
- MySQL: 8.0

# 解決法(It works for me)
タスクマネージャーから、mysqld.exe を終了する。

# 原因
起動中の mysqld.exe がポート番号 3306 を既に使用していた。docker-compose.yml ファイルで MySQL のポート番号を 3306 に指定していたため、ポート番号が被っていた。

# 解決に至るまでに行ったこと

1. `docker-compose up -d` 実行、失敗
最初に書いた通り。コンテナの実行に失敗している。起動したが途中で強制終了したわけでもなさそうだった。

2. `docker-compose` コマンドのログを表示して原因を特定
verbose オプションでログを表示。以下のコマンドを実行することで、`docker-compose` コマンドのログをターミナル上に表示することができる。ログが止まった箇所がコンテナ構築を阻害している可能性が高い。（私の場合は `docker-compose up` コマンドで PHP 側のコンテナは起動できていたため、既に原因は特定できていた。）
   ```
   docker-compose --verbose build --no-cache
   ```

3. ポート番号 3306 でリッスンしているプロセスを調査
docker-compose.yml ファイルで 3306 番ポートを指定していたことを思い出す。ポートが既にバインドになっていることを疑い、3306 番のポート番号にリッスンするプロセスを探す。以下のコマンドを実行。`netstat` コマンドでネットワークの接続状況や状態を確認する。  
-a, -n, -o オプションでそれぞれ、すべてのアクティブなTCP接続の状態、アドレスとポート番号（数字）、接続に関連するプロセスID（PIDとも。ソケット・オプション統計情報、フラグ統計情報、 およびバッファー統計情報などの、ソケットに関する詳細なデータ。-a, -n オプションと併用）を表示する。
   ```
   netstat -ano | findstr ":3306"
   ```
    実行した結果が以下のようになっており。ポート番号 3306 番のプロセスによって、プロセスID 5464 がアクティブになっていることがわかった。
   ```
     TCP         0.0.0.0:3306           0.0.0.0:0              LISTENING       5464
     TCP         0.0.0.0:33060          0.0.0.0:0              LISTENING       5464
     TCP         [::]:3306              [::]:0                 LISTENING       5464
     TCP         [::]:33060             [::]:0                 LISTENING       5464
   ```
  
4. プロセスIDが 5464 のプロセスを探す
`tasklist` コマンドで、ローカルまたはリモートで実行中のプロセスの一覧を表示する。実行するコマンドは以下のようになる。

   ```
   tasklist /FI "PID eq 5464"
   ```
   /fi オプションでフィルターを行う。後に続く "○○" が条件。今回は、PID = 5464 となるプロセスを探す。実行結果が、下のようになった。

   ```
   イメージ名                     PID セッション名     セッション# メモリ使用量
   ========================= ======== ================ =========== ============
   mysqld.exe                    5464 Services                   0     44,404 K
   ```
   どうやらmysqld.exe というイメージ名のプロセスが PID 5464 となっており、ポート番号 3306 をバインドしている原因であるとわかった。

5. タスクマネージャーから mysqld.exe を終了
タスクマネージャー -> 「詳細」タブから、mysqld.exe を右クリックして終了。この後、`docker-compose up` コマンドが動いた。

# 再発防止
今後同じ手順でこのプロセスを踏むのは面倒なので、docker-compose.yml ファイルの記述を変える。大人しく別のポート番号に変えるのが楽で確実。

変更前：
```
ports:
  - '3306:3306'
```

変更後：
```
ports:
  - '3307:3306'
```

# docker-compose.yml ファイルの記述
PHP と MySQL の環境構築がうまくいった docker-compose.yml ファイルの記述を最後に記す。適宜 name などは変えてほしい。私は気象APIを叩くアプリケーションを開発するために環境構築をしたため、それに関係した名前となっている。

docker-compose.yml :
```
version: '3.7'
services:
  app:
    build:
      context: ./docker/php
      dockerfile: Dockerfile
    container_name: php-container
    image: php:7.3-apache
    volumes:
      - ./src:/var/www/html
    ports:
      - 8080:80
    depends_on:
      - db

  db:
    container_name: mysql-container
    image: mysql:8.0
    build:
      context: ./docker/mysql
      dockerfile: Dockerfile
    volumes:
      - ./docker/mysql/data:/var/lib/mysql
    ports:
      - '${FORWARD_DB_PORT}:3306'
    environment:
      MYSQL_DATABASE: '${DB_DATABASE}'
      MYSQL_USER: '${DB_USER}'
      MYSQL_PASSWORD: '${DB_PASSWORD}'
      MYSQL_HOST: '${DB_HOST}'
      MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
      MYSQL_ROOT_HOST: '%'
      TZ: '${TZ}'
```

環境変数をまとめた .env ファイル : 
```
COMPOSE_PROJECT_NAME=docker-compose-mysql
DB_HOST=host_name
DB_DATABASE=database_name
DB_USER=user_name
DB_PASSWORD=password
TZ=Asia/Tokyo
FORWARD_DB_PORT=3306
```

# おわりに
同じ症状でない場合でも、`docker-compose up` コマンドがどこで止まっているかを特定するために、`docker-compose --verbose build --no-cache` コマンドを実行するだけでも解決の糸口となるのではないだろうか。

# 参考文献
- [dockerコンテナ起動時にOnly one usage of each socket addressというエラー (別記事： @tbzgkzejyk1ef5s91wuf(ずび ずば) 様より)]("https://qiita.com/tbzgkzejyk1ef5s91wuf/items/cc2be6263523149d7cbe")

- [Docker-Composeで3306以外のポートでmysqlを起動 (別記事： @SFITB(Mr Drone) 様より)](https://qiita.com/SFITB/items/2170fb8cadd820951f64)

- [netstat | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows-server/administration/windows-commands/netstat)

- [tasklist | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows-server/administration/windows-commands/tasklist)