[Docker] MySQLコンテナ接続時のポート競合エラー解決方法 - Homebrewとの衝突ケース

## はじめに

「開発系エンジニアのためのDocker絵とき入門」でMySQLコンテナを学習中、思わぬエラーに遭遇しました。
この記事では、私が遭遇したポート競合の問題と、その解決方法を共有します。

### 対象

- Dockerを使い始めた初心者の方
- MySQLコンテナの接続で「ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)」エラーに遭遇した方

### 実行環境

- OS: Windows 11 + WSL2 (Ubuntu 22.04)
- Docker version 24.0.7
- MySQL 8.2.0 (Dockerコンテナ)
- MySQL 8.0.39 (Homebrew)

### 注記

開発初心者が書いた記事です。間違いを含む可能性があります。
もし間違いに気づかれた方はコメントにてお知らせいただけると幸いです。

### コマンドの読み方

- `$` で始まる行：入力するコマンド
- それ以外の行：コマンドの実行結果
- `\` ：コマンドが次の行に続くことを示す
- `#` で始まる行：説明のコメント

## 発生したエラー

MySQLのDockerコンテナを起動してホストPCから接続しようとした際、以下のような不可解な動作が発生しました。

```bash
# MySQLコンテナの起動
$ docker run -d \
  --name db \
  -e MYSQL_ROOT_PASSWORD=secret \  #passwordはsecret
  -e MYSQL_ROOT_HOST='%' \
  -v mysql_data:/var/lib/mysql \
  -p 3306:3306 \
  mysql:8.2.0

# ホストPCからパスワードありで接続を試みる → 失敗
$ mysql -h 127.0.0.1 -P 3306 -u root -psecret
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

# パスワードなしで接続を試みる → 成功（なぜ？）
$ mysql -h 127.0.0.1 -P 3306 -u root
Welcome to the MySQL monitor...
Server version: 8.0.39 Homebrew
```

コンテナ内から直接接続できるか確認したところ、passwordありで接続できました。

```bash
# コンテナ内でMySQLに接続（パスワードあり）
$ mysql -u root -psecret
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.2.0 MySQL Community Server - GPL

# 試しにパスワードなしで接続
$ mysql -u root
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
```

以上から、

- Dockerコンテナ内のMySQLは正常に動作している
- ホストPCからの接続がうまくいっていない

ことがわかりました。

![Dockerコンテナ (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3903879/ab77214e-63df-3e77-76d8-8ce7f108e167.png)

## 原因の特定

接続成功時に表示されたサーバーバージョン `8.0.39 Homebrew` に注目しました。これは、Dockerで指定したMySQL（8.2.0）ではありません。

一応接続成功後にプロセスを確認してみると、port :3306にmysqlが接続されいることがわかります。

```bash
$ lsof -i :3306
COMMAND PID USER       FD   TYPE DEVICE SIZE/OFF NODE NAME
mysqld  669 username   23u  IPv4  24543      0t0  TCP localhost:mysql (LISTEN)
```



以上の結果から、ターミナルから`mysql`を呼び出すと、Homebrew版のMySQLが呼び出されることがわかりました。（そして、homebrew版にはpasswordを設定していなかったことも同時に判明しました。）

![Dockerコンテナ (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3903879/e9762cc1-0c45-4fdc-1a1a-ea7ae1589faf.png)


## 解決方法

### Homebrew版MySQLの停止

```bash
# PIDを直接指定して強制終了
$ kill 669  # PIDは"lsof -i :3306"で確認

# 確認（何も表示されなければ停止に成功している）
$ lsof -i :3306
```

### Dockerコンテナの起動

```bash
# ボリュームの作成
$ docker volume create mysql_data

# MySQLコンテナの起動(\は入力が続いていることを示している)
$ docker run -d \
  --name db \
  -e MYSQL_ROOT_PASSWORD=secret \
  -e MYSQL_ROOT_HOST='%' \
  -v mysql_data:/var/lib/mysql \
  -p 3306:3306 \
  mysql:8.2.0
```

### 接続確認

```bash
$ mysql -h 127.0.0.1 -P 3306 -u root -psecret
Welcome to the MySQL monitor...
Server version: 8.2.0 MySQL Community Server - GPL
```

無事port :3306でdockerコンテナ上のMySQLに接続できました！

## まとめ

### 学んだこと

- 実行時に何が動いているかを確認する重要性
- プロセス確認コマンド（lsof）の使い方

### トラブルシューティングのポイント

1. 接続時はサーバーバージョンを確認
2. `lsof -i :ポート番号` でプロセスの確認
3. 意図しないプロセスがある場合は適切に停止

振り返ってみると、Dockerのエラーメッセージと全く関係のないところで躓いていたことがわかりました。

ただ、エラーを解決する過程で、MySQLがv8以降で認証方式に変更があったことや、ERROR1045(28000)のエラーの解決策について学ぶことができたので、よしとしたいと思います。