DockerでMySQLを使っていて、ユーザーを作成したのにそのユーザーで接続できないときの原因と対処方法です
作成したユーザーで接続できない問題
Dockerのコンテナで動作しているMySQLに任意のユーザーを作成し、そのユーザーでPHPプログラムから接続しようとしてもエラーとなる問題の対処方法です。
以下のようなエラーが発生する場合となります。
エラー:SQLSTATE[HY000] [1045] Access denied for user 'foouser'@'172.19.0.3' (using password: YES)
これは例えば以下のPHPプログラムを動かしたときにエラーとなるケースです。
<?php
$dsn = 'mysql:host=mysql;dbname=foodb;charset=utf8';
$user = 'foouser';
$password = 'password';
try {
$db = new PDO($dsn, $user, $password,[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,]);
$stmt = $db->prepare(
"SELECT * FROM users ORDER BY birthday DESC"
);
} catch (PDOException $e) {
header('Content-Type: text/plain; charset=UTF-8', true, 500)
exit($e->getMessage());
}
?>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<?php
while ($row = $stmt->fetch()):
?>
<p>名前:<?php echo $row['name'] ?></p>
<p>誕生日:<?php echo $row['birthday'] ?></p>
<?php
endwhile;
?>
</body>
</html>
ここでユーザーは「foouser」、パスワードは「password」です。
MySQLにrootではいって以下の作業でMySQLにこのユーザーを作成しています。
DockerのMySQLにrootで入る
$ docker exec -it docker-mysql bash # mysql -u root -p
ユーザーの作成
GRANT ALL ON user_db.* to 'foouser'@'localhost' IDENTIFIED BY 'password'; FLUSH PRIVILEGES;
エラーの発生する原因を結論からいうと、ユーザー作成時に’localhost’を指定しているからです。
Docker以外で構築されたLAMP環境(例えば:VMのLinux、XAMPP、MAMPなど)ではドメインのlocalhostでMySQLと接続できるためエラーは発生しません。
しかしDockerのMySQLは外部アプリなどからlocalhostで接続することができません。
上記のPHPプログラムの1行目にあるDSN(Data Source Name)を見てください。
‘mysql:host=mysql;dbname=foodb;charset=utf8’と書かれていますが、「host=mysql」となっています。
MySQLと接続するときに指定するhostはローカル環境だと一般的には「localhost」となります。
ですがDockerの場合はlocalhostでは接続できず、サービス名で接続する必要があります。
この場合、DockerのMySQLは「mysql」というサービス名で動作しているのでこのような記述となります。
サービス名で接続したあとでDockerではローカルアドレスを自動で割り振ります。
それが、エラーメッセージで表示されていた「172.19.0.3」です。
つまりlocalhost(172.0.0.1)では接続できないのです。
なのでデータベースにユーザーを作成するときにホスト名をlocalhostとすると上記エラーが発生してしまいます。
対処方法としては、データベースに作成するユーザーのホスト名をDockerが割り当てたIPにするか、’%’を指定するとエラーは解消されます。
ちなみ’%’は全てのホストという意味となります。
接続可能なユーザーの作成
GRANT ALL ON user_db.* to 'foouser'@'%' IDENTIFIED BY 'password'
作成済みのユーザーの情報を変更したい場合は、
RENAME USER 'foouser'@'localhost' to 'foouser'@'%'; FLUSH PRIVILEGES;
もしくは、phpMyAdminを使えるようにしていた場合は、ユーザーアカウントのページで対象ユーザーの「特権を編集」をクリックして変更できます。
DockerのMySQLとPHPの環境
参考にここで作成しているDockerのLAMP環境は、以下のDocker Composeを使っています。
【docker-compose.yml】
version: '3.7' services: mysql: image: mysql:5.7 container_name: docker-mysql volumes: - db_data:/var/lib/mysql restart: always environment: MYSQL_ROOT_PASSWORD: 'password' phpmyadmin: container_name: docker-phpmyadmin depends_on: - mysql image: phpmyadmin/phpmyadmin environment: PMA_HOST: mysql restart: always ports: - "8080:80" php-apache: container_name: docker-php-apache build: ./php volumes: - ./htdocs:/var/www/html restart: always ports: - "80:80" depends_on: - mysql volumes: db_data: {}
【Dockerfile】
FROM php:7.3-apache COPY ./php.ini /usr/local/etc/php/ RUN apt-get update \ && apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng-dev \ && docker-php-ext-install pdo_mysql mysqli mbstring gd iconv
【php.ini】
[Date] date.timezone = "Asia/Tokyo" [mbstring] mbstring.internal_encoding = "UTF-8" mbstring.language = "Japanese"
LAMP環境作成の詳細は以下の記事を参照してください。