Docker の mysql コンテナに mysql コマンドで接続できない
はじめに
今回、Dcoker の mysql コンテナを起動している状態で、mysql コマンドで接続できませんでした。解決に時間がかかったため、内容を共有します。
環境
$ sw_vers
ProductName: macOS
ProductVersion: 15.5
BuildVersion: 24F74
$ docker --version
Docker version 28.3.0, build 38b7060
$ docker compose version
Docker Compose version v2.38.1-desktop.1
$ mysql --version
mysql Ver 9.3.0 for macos15.4 on arm64 (Homebrew)
状況
最初に、どのような状況だったのかを説明します。
mysql コンテナ
以下の docker-compose.yml と my.cnf ファイルがあるとします。
services:
mysql:
image: mysql:8.0
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
volumes:
- ./my.cnf:/etc/mysql/conf.d/my.cnf
environment:
MYSQL_ROOT_USER: root
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: sample
ports:
- "3306:3306"
[mysqld]
character-set-server=utf8mb4
character-set-client-handshake=FALSE
collation-server=utf8mb4_unicode_ci
ft_min_word_len=1
innodb_ft_min_token_size=1
innodb_ft_enable_stopword=0
ngram_token_size=1
default_authentication_plugin=mysql_native_password
[client]
default-character-set=utf8mb4
mysql コンテナを起動します。
$ docker compose up -d
[+] Running 2/2
✔ Network my-configs_default Created
✔ Container my-configs-mysql-1 Started
$ docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
my-configs-mysql-1 mysql:8.0 "docker-entrypoint.s…" mysql 5 seconds ago Up 4 seconds 0.0.0.0:3306->3306/tcp, [::]:3306->3306/tcp
無事に起動できていますね。
接続状況
mysql コマンドを使用し、mysql コンソールに接続してみましょう。
$ mysql -h 127.0.0.1 -u root -ppassword -P 3306 sample
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
エラーとなってしまいました。docker compose コマンドだとどうでしょうか?
$ docker compose exec mysql mysql -h 127.0.0.1 -u root -ppassword -P 3306 sample
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.0.42 MySQL Community Server - GPL
Copyright (c) 2000, 2025, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sample |
| sys |
+--------------------+
5 rows in set (0.01 sec)
なんと、成功します。つまり、ローカルの mysql コマンドでは mysql に接続できず、Docker コンテナ内からは mysql に接続できるのです。ホスト名やユーザー名など、使用しているパラメータの値は同じです。いったいどういうことでしょうか?
原因
筆者の場合の原因は、ローカルで mysql サーバーを起動していたことでした。
$ brew services info mysql
mysql (homebrew.mxcl.mysql)
Running: ✔
Loaded: ✔
Schedulable: ✘
User: user
PID: 46630
これにより、ローカルの Docker コンテナではなく、ローカルの mysql サーバーに接続してしまっていました。そのため、docker compose コマンド経由ではコンテナ内の msyql への接続に成功し、mysql コマンド経由ではコンテナ内の myql への接続に失敗していました。
解決策
ローカルの mysql サーバーを停止しましょう。
$ brew services info mysql
mysql (homebrew.mxcl.mysql)
Running: ✘
Loaded: ✘
Schedulable: ✘
これで、ローカルからも mysql へ接続できるようになりました。
$ mysql -h 127.0.0.1 -P 3306 -u root -ppassword sample
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 12
Server version: 8.0.42 MySQL Community Server - GPL
Copyright (c) 2000, 2025, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sample |
| sys |
+--------------------+
5 rows in set (0.001 sec)
解説
ここから周辺情報を調べ、一体何が起こっていたのかを深掘りします。
いったい何が起こっていたのか?
元々は、ローカルから mysql に接続する必要性が生じ、以下のような状況でした。
$ docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
my-configs-mysql-1 mysql:8.0 "docker-entrypoint.s…" mysql 5 seconds ago Up 4 seconds 0.0.0.0:3306->3306/tcp, [::]:3306->3306/tcp
$ mysql --version
zsh: command not found: mysql
$ which mysql
mysql: aliased to nocorrect mysql
そのため、brew install mysql で mysql をインストールしました。
$ brew install mysql
...
We've installed your MySQL database without a root password. To secure it run:
mysql_secure_installation
MySQL is configured to only allow connections from localhost by default
To connect run:
mysql -u root
To start mysql now and restart at login:
brew services start mysql
Or, if you don't want/need a background service you can just run:
/opt/homebrew/opt/mysql/bin/mysqld_safe --datadir\=/opt/homebrew/var/mysql
このとき、最後の brew services start mysql が目に留まり、そのまま実行していたのです。
$ brew services start mysql
==> Successfully started `mysql` (label: homebrew.mxcl.mysql)
これにより、ローカルで mysql サーバーが起動していました。
mysql サーバーを起動するとどうなるのか?
brew services info mysql はローカルに mysql サーバーを起動するコマンドでした。
mysql サーバーはデフォルトで以下の設定で起動します。
[mysqld]
port=3306
bind-address=127.0.0.1
つまり、ポート 3306 が docker コンテナと mysql サーバーで競合していました。以下のコマンドからも確認できます。
$ sudo lsof -i:3306
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
com.docke 1991 user 168u IPv6 0x1ed0be9b779fe32e 0t0 TCP *:mysql (LISTEN)
mysqld 56090 user 21u IPv4 0xdd71e69fd3126c43 0t0 TCP localhost:mysql (LISTEN)
なぜ、ポート 3306 が競合しているにも関わらず、両方とも起動に成功しているのか?
ポートが競合するなら、後から起動したプロセスは実行に失敗するのでないでしょうか?
LLM に聞いたところ、異なるインターフェース(* と localhost)にバインドされているため共存できるとのことでした。
| プロセス | バインドアドレス | ポート | 状態 |
|---|---|---|---|
com.docker.backend |
*(全インターフェース) |
3306 | LISTEN |
mysqld(Homebrew) |
localhost(127.0.0.1) |
3306 | LISTEN |
バインド先には IPv6 の *(全インターフェース)と IPv4 の localhost(127.0.0.1)があります。
| バインド先 | 説明 |
|---|---|
* (0.0.0.0) |
全てのネットワークインターフェースにバインド(localhost 含む)。ホストの外部 IP でも接続できる。 |
127.0.0.1 |
ローカルループバック専用。外部からはアクセスできない。 |
実行した mysql コマンドでは、ホスト名に 127.0.0.1 を指定していました。そのため、ローカルで起動している mysql サーバーに接続してしまっていたのです。
どうすればよかったのか?
Dcoker コンテナで mysql を起動するなら、ローカルで mysql サーバーを起動することはないでしょう。mysql パッケージではなく、mysql-client パッケージのインストールで十分です。
$ brew uninstall mysql
$ brew install mysql-client
また、mysql-client には server コンポーネントが含まれていません。仮に mysql サーバーを起動しようとしてもエラーになります。
$ brew services start mysql
Error: Formula `mysql` is not installed.
終わりに
最初はネットワーク周りが原因であることに気づかず、コマンドの引数を試行錯誤して時間を浪費しました。どなたかのお役に立てましたら幸いです。
Discussion