はじめに
Docker環境でMySQLコンテナを使用した際に、他のコンテナから接続できない旨のエラーが出力されて詰まったので備忘も兼ねて残しておこうと思います。
環境
OS:MacBookPro M3
使用コンテナのイメージ等
- maven:3.6.3-adoptopenjdk-14
- python:3.8
- mysql:8.0
経緯
他のコンテナ(maven, python等)から、MySQLサーバーのコンテナに接続して機能テストを実行しようとしたところ、以下のようなエラーが発生しました。
いずれもDB関連のエラーなのでMySQLサーバーのコンテナ周りに問題がありそうでした。
sqlalchemy.exc.ProgrammingError: (mysql.connector.errors.ProgrammingError) 1044 (42000): Access denied for user 'user'@'%' to database 'sample_db1'
(Background on this error at: https://sqlalche.me/e/14/f405)
そこで、MySQLサーバーのコンテナを確認してみると、コンテナには接続できることと、sample_db1
というデータベースが存在していることが確認できました。
続いて、権限を確認してみたところ、以下のように権限が足りていないことがわかりました。
mysql> SHOW GRANTS FOR 'user'@'%';
+----------------------------------+
| Grants for user@% |
+----------------------------------+
| GRANT USAGE ON *.* TO user@% |
+----------------------------------+
1 row in set (0.01 sec)
問題の原因
コンテナをビルドする際に以下のSQLスクリプトを使用していたことが原因でした。
CREATE DATABASE IF NOT EXISTS sample_db1;
CREATE DATABASE IF NOT EXISTS sample_db2;
CREATE USER 'user'@'localhost' IDENTIFIED BY 'password';
GRANT ALL ON sample_db1.* TO 'user'@'localhost' WITH GRANT OPTION;
GRANT ALL ON sample_db2.* TO 'user'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
この設定だと、ユーザー'user'@'localhost'
はMySQLコンテナ内(localhost)からしか接続できません。他のコンテナからは'user'@'%'
として接続しようとするため、権限が不足してエラーになります。
解決方法
ユーザーのホスト部分を修正して、任意のホストから接続できるようにします。
また、既存のユーザーがいる場合にエラーになってしまう可能性があるため、IF NOT EXISTS
を使いました。
修正後のSQLスクリプト
CREATE DATABASE IF NOT EXISTS sample_db1;
CREATE DATABASE IF NOT EXISTS sample_db2;
CREATE USER IF NOT EXISTS 'user'@'%' IDENTIFIED BY 'password';
ALTER USER 'user'@'%' IDENTIFIED BY 'password';
GRANT ALL ON sample_db1.* TO 'user'@'%' WITH GRANT OPTION;
GRANT ALL ON sample_db2.* TO 'user'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
ポイント
-
CREATE USER IF NOT EXISTS
でユーザーが存在しない場合のみ作成 -
ALTER USER
でパスワードを再設定し、既存ユーザーでも確実にパスワードを適用 -
'user'@'%'
で任意のホストからの接続を許可
コンテナの再ビルドと確認
修正したスクリプトを使ってMySQLコンテナを再ビルドします。
docker compose up -d --build
MySQLコンテナに入り、ユーザーの権限を確認します。
docker exec -it mysql-container mysql -u root -p
SHOW GRANTS FOR 'user'@'%';
期待通りの権限が表示されればOKです。
注意点
-
'user'@'%'
は任意のホストからの接続を許可するため、セキュリティ上のリスクがあります。本番環境では接続元を限定することをおすすめします。
CREATE USER IF NOT EXISTS 'user'@'192.168.0.%' IDENTIFIED BY 'password';
ALTER USER 'user'@'192.168.0.%' IDENTIFIED BY 'password';
- 既存のユーザーがいる場合、
CREATE USER
だけではエラーになるので、IF NOT EXISTS
とALTER USER
を組み合わせています。
おわりに
この修正により、他のコンテナからMySQLコンテナへの接続が可能になりました。
同じ問題で困っている方の参考になれば幸いです。
参考リンク