1.はじめに
今までDockerなんて触ったこともなかった僕が、ちょっとした出来心でDockerを勉強したいなと思った話については下記の記事を読んでいただけると幸いです。
今回はMySQLでrootユーザーが使えなかった件の原因と解決方法についてまとめていきたいと思います。
2.事象
立ち上げたMySQLに対して、PHPプログラムかやphpMyAdminからrootユーザーでログインできない。
なお、ログインを試みた際のエラーメッセージは下記の画像になります。
この時のdocker-compose.ymlとDockerfileは下記の通りです。
version: '3.8'
volumes:
mysql_db: {}
services:
phpmyadmin:
image: phpmyadmin
environment:
PMA_HOST: mysql
ports:
- '8002:80'
mysql:
platform: linux/amd64
image: mysql/mysql-server:5.7
volumes:
- mysql_db:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: '12345678'
ports:
- '3306:3306'
httpd:
build: .
volumes:
- ./htdocs:/var/www/html
ports:
- '8001:80'
FROM php:7.3-apache
RUN docker-php-ext-install pdo_mysql
また、PHPのプログラムファイルは下記のようにデータベースに接続するだけのプログラムと内容になっています。
<?php
try{
$db = new PDO('mysql:host=mysql;dbname=mysql','root','12345678');
$msg = 'Connected To MySQL';
print $msg;
}catch(PDOException $e){
$msg = 'Failed connect to MySql(' . $e->getMessage() . ')';
print $msg;
}
?>
3.原因
rootユーザーがローカルからのみログインを許可している状態であったことが原因でした。
4.解決方法
外部からアクセスできるようにするには、コンテナを立ち上げてからコマンドで手動でアクセス権限を変更するか、コンテナ立ち上げ時に自動でコマンドを実行するかの二択になると思います。
手動でコマンドを実行するとなると、破棄後のコンテナ立ち上げの度に行わないといけないので、それでは面倒臭いと思いますので、今回はコンテナ立ち上げ時に自動で行う方法を採用したいと思います。
今回は下記の二つのことを行い、コンテナ立ち上げ時にrootユーザーの設定を自動で行うようにします。
・docker-compose.ymlの変更
docker-compose.ymlを下記のように書き換えます。
version: '3.8'
volumes:
mysql_db: {}
services:
phpmyadmin:
image: phpmyadmin
environment:
PMA_HOST: mysql
ports:
- '8002:80'
mysql:
platform: linux/arm64/v8
image: mysql/mysql-server:8.0
volumes:
- mysql_db:/var/lib/mysql
- ./initdb.d:/docker-entrypoint-initdb.d
environment:
MYSQL_ROOT_PASSWORD: '12345678'
# MYSQL_USER: 'user'
# MYSQL_PASSWORD: 'pass'
ports:
- '3306:3306'
httpd:
build: .
volumes:
- ./htdocs:/var/www/html
ports:
- '8001:80'
「./initdb.d:/docker-entrypoint-initdb.d」を追加して、docker-compose.ymlと同じパスにある「initdb.d」内にある「.sql」「.sh」「.sql.gz」のファイルを実行してくれるらしいです。
・initdb.dフォルダの作成
docker-compose.ymlと同じパスにディレクトリ「initdb.d」を作成します。
・SQLファイルの作成
SQLファイルを作成し下記の内容を記載します。
RENAME USER 'root'@'localhost' TO 'root'@'%';
これで、コンテナを立ち上げるたびに、
5.調査経緯
役に立つか分かりませんが、どのような経緯で原因と解決方法に行き着いたかをまとめておきます。
まず、大体docker内部のネットワークの問題か、ユーザー設定の問題かどちらかに原因があると仮定しました。
そこで、一旦rootユーザーでログインすることを諦めて、コンテナ立ち上げ時に別のユーザーを作成して、ログインできるかを確認してみました。
その時のdocker-compose.ymlが下記の通りです。
version: '3.8'
volumes:
mysql_db: {}
services:
phpmyadmin:
image: phpmyadmin
environment:
PMA_HOST: mysql
ports:
- '8002:80'
mysql:
platform: linux/amd64
image: mysql/mysql-server:5.7
volumes:
- mysql_db:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: '12345678'
MYSQL_USER: 'user'
MYSQL_PASSWORD: 'pass'
ports:
- '3306:3306'
httpd:
build: .
volumes:
- ./htdocs:/var/www/html
ports:
- '8001:80'
これでコンテナを立ち上げたところ、phpMyAdminからでもPHPプログラムからでも、ログインすることができました。
ここで普通に作成したユーザーを使用して開発を進めてもいいんでしょうけど、今後のためにモヤモヤするのはよくないと思い、原因を探ります。まあ、新規で作成したユーザーは権限が全く付与されていないため、あまり使い物にならないので、そこら辺を開発の際どうすればいいのかというところも含めて調べてみたというところもあります。
これで一つ目のDocker内部のネットワークの問題ではないことが分かりましたので、おそらく権限か、そもそもパスワードの変更ができていないなどユーザー設定の問題であることが予想するところまでできました。
なので、立ち上げているDocker内のMySQLにコマンドで操作してrootのユーザー設定についてみてみました。
まずは、下記のコマンドでMySQLを立ち上げているのコンテナの内部に入り、コマンドで操作できるようにします。
$ docker compose exec mysql bash
続いて、コンテナの中でMySQLにログインします。
$ mysql -u root -p
これでログインすることができたので、docker-compose.ymlでのパスワード設定がミスっているという可能性が消えました。
続いて権限系の問題を調査してみます。MySQLにログインした状態で下記SQLを実行します。
SELECT host, user FROM mysql.user;
下記の結果を見てみたところ、コンテナ立ち上げ時に作成したユーザーは外部からアクセスできますが、rootユーザーは、localhostからしかアクセスできないようです。おそらく、これが原因なのではないかと考えられます。
正直、コンテナの概念をちゃんと理解したとは言えないのでこの場合のローカルってどこのことを指すんだろうという感じですが、とりあえず調査を進めます。
とりあえず、このrootユーザーの「localhost」を「%」に書き換えていきます。
MySQLにログインした状態で下記のSQL文を実行します。
RENAME USER 'root'@'localhost' TO 'root'@'%';
これでPHPやphpMyAdminからログインできるかを試してみます。
ログインできたので、これでrootユーザーでログインできない問題は解決です。
あとは、いちいちこの作業をコマンドを使用してするのも面倒臭いので、コンテナ立ち上げ時に自動で実行する方法を調査して完了となります。
6.末筆
なんやかんや普段データベース操作はGUIツールなんかを使っているので、ユーザー設定を調べるだけとはいえ、コマンドでデータベースを触るのは新鮮でした。多分、研修の時以来かな。
参考書通りにやっても動かないというのは、少し大変な反面、知識や経験に繋がるんだなと思いました。
もう少しDockerを使い慣れていきたいと思います。
〜参考サイト〜