こんにちは、 @dz_ こと大平かづみです。
Prologue
掲題の通り、 mysqlのオフィシャルイメージを使ったコンテナにアクセスしようとすると ER_NOT_SUPPORTED_AUTH_MODE
というエラーが発生して困ったので解決方法を書き留めます。
環境
一部省略していますが、このようなコンテナ構成です。apiコンテナからdbコンテナにアクセスします。apiコンテナは Node.js(TypeScript) で構成していますが、検索してみると php でも同様の事象が起こっているようなので言語には依存しないと考えられます。
version: "3.7"
services:
api:
build:
context: ./<somewhere>
dockerfile: Dockerfile
container_name: api
links:
- db
environment:
MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
db:
image: mysql:8
container_name: db
volumes:
- db-data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
volumes:
db-data:
external:
name: db-data
エラー内容
これは TypeORM を利用して mysql にアクセスしようとした際のエラーメッセージです。前述したように、言語やライブラリに関連なく php などでも同様のエラーメッセージが出力されるようです。
Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client
解決方法
調べてみたところ、Authentication plugin に mysql_native_password
を指定すれば、パスワードによるログインが許可されるようです。おそらく、セキュリティの観点ではデフォルトから変えないほうがよさそうですが、開発段階ではいったん緩めてしまおうと思います。
さて、mysqlイメージを用いたコンテナにこの mysql_native_password
を設定するには?ドキュメントによると、 _docker-composeでは
commandに
--default-authentication-plugin=mysql_native_password` を指定すればよいようです。
db:
image: mysql:8
container_name: db
volumes:
- db-data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
command: --default-authentication-plugin=mysql_native_password # <- 追加
が、私の環境では効かず、設定を確認したところ、下記のように caching_sha2_password
があたっていました。どうやら、このオプションを設定する前に作ったユーザーに対してはすでにデフォルトの設定が適用されていたようです。
mysql> SELECT Host, User, plugin from mysql.user;
+-----------+------------------+-----------------------+
| Host | User | plugin |
+-----------+------------------+-----------------------+
| % | you | caching_sha2_password |
| % | root | caching_sha2_password |
| localhost | mysql.infoschema | caching_sha2_password |
| localhost | mysql.session | caching_sha2_password |
| localhost | mysql.sys | caching_sha2_password |
| localhost | root | caching_sha2_password |
+-----------+------------------+-----------------------+
6 rows in set (0.00 sec)
そこで、データを一度リセット(私の場合は volume を削除・新規作成)してからコンテナ群を起動すると、ユーザーに mysql_native_password
が設定されました!
mysql> SELECT Host, User, plugin from mysql.user;
+-----------+------------------+-----------------------+
| Host | User | plugin |
+-----------+------------------+-----------------------+
| % | you | mysql_native_password |
| % | root | mysql_native_password |
| localhost | mysql.infoschema | caching_sha2_password |
| localhost | mysql.session | caching_sha2_password |
| localhost | mysql.sys | caching_sha2_password |
| localhost | root | mysql_native_password |
+-----------+------------------+-----------------------+
6 rows in set (0.01 sec)
ちなみに、手動でこのプラグインを変更するには、下記の操作でできます。
docker exec -it db mysql -u root -p
Enter password:
mysql> ALTER USER 'you'@'%' IDENTIFIED WITH mysql_native_password BY 'your-password';
Epilogue
ということで、これで作業再開できます~