dockerを使ってデータベースやwordpressを構築するときに、接続先のデータベース名前など設定をカスタマイズすると、データベースに接続できないというエラーが発生することがある。
しかも、以前は同じdocker-compose.ymlで問題なく動いていたのに、、急にエラーがでてきた、、なんで、、?という、あくまでdocker-compose.ymlに問題がない場合、原因はDocker上で起動するMySQLの性質にあります。
この症状の原因と対処法について解説します。
サクッと解決方法
原因や理由はどうでもいいという方のために、結論のみのサクッと解決する方法をまとめておきます。
※< >の部分を自分の設定に変更してください。
#MySQLのコンテナに入る
> docker exec -it <コンテナ名> bash
#ルートユーザー権限でMySQLの対話モードに入る
root@dab19e479a65:/# mysql -u <ルートユーザー名> -p<ルートユーザーのパスワード>
#対象ユーザーにデータベースへのアクセス権限を付与する
mysql> grant all privileges on *.* to '<ユーザー名>'@'<ホスト名>';
#対象のデータベースを作成する
mysql> create database <データベース名>;
あとは、ブラウザをリロードすればWordpressインストールのいつもの画面が表示されます。
エラーの内容、原因、対処法の詳細については以下。
エラー内容
エラーは、ログインのために指定したユーザーが、指定したデータベースにアクセスできないという症状。
Access denied for use ‘ユーザー名’@’ホスト名’ to database ‘データベース名’
Can’t select database
We were able to connect to the database server (which means your username and password is okay) but not able to select the データベース名 database.
Are you sure it exists?
Does the user wp_user have permission to use theデータベース名 database?
On some systems the name of your database is prefixed with your username, so it would be like username_データベース名. Could that be the problem?
If you don’t know how to set up a database you should contact your host. If all else fails you may find help at the WordPress Support Forums.
docker-compose.ymlの設定例は以下。
p-wp:
image: wordpress:latest
container_name: prograshi_wp
#restart: always
depends_on:
- db
ports:
- "10090:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wp_user
WORDPRESS_DB_PASSWORD: root
WORDPRESS_DB_NAME: prograshi_db
WORDPRESS_DEBUG : 1
volumes:
- ./prograshi:/var/www/html
発生原因
Dockerのコンテナを使ってWordpressのサイトを構築するとき、rootユーザー以外を指定した場合、そのユーザーに与えられるアクセス権限は初回に作成した1つのデータベースのみとなる。
このため、同じMySQLサーバーに複数のWordpressサイトのデータベースを作成するときに、同一ユーアーで異なるデータベース名を指定した場合に、アクセス権限がなく「Access denied for use ‘ユーザー名’@’ホスト名’ to database ‘データベース名’」というエラーが発生する。
エラーが発生する状況は以下の3つが重なった時。
逆に、以下の4つのうち、どれかに該当すれば同じdocker-compose.ymlで問題なくWordpressサイトを起動することができる。
対処法
この問題は、データベースにアクセスしようとしているユーザーの権限を変更することで解決できる。
Dcoker上のコンテナに入り、権限を変更し、ブラウザをリロードしてWordpressを構築していきます。
Docker上のMySQLコンテナに入る
まずは 、docker ps コマンドで、現在起動しているコンテナを確認する。
> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
db17e4d0fc2b wordpress:latest "docker-entrypoint.s…" 42 hours ago Up 28 hours 0.0.0.0:10090->80/tcp, :::10090->80/tcp wp
d01dd3b83a41 phpmyadmin/phpmyadmin:latest "/docker-entrypoint.…" 42 hours ago Up 28 hours 0.0.0.0:10099->80/tcp, :::10099->80/tcp phpmyadmin
dab19e479a65 mysql:5.6 "docker-entrypoint.s…" 42 hours ago Up 28 hours 3306/tcp wp_mysql
上記例の場合、3つのコンテナが起動している。(1)WordPress, (2)phpMyAdmin, (3)MySQL。この中でMySQLの対話モードに入れるのは(3)MySQL コンテナ。(phpMyAdminではない)
コンテナの中に入るコマンドは以下。
$docker exec -it コンテナ名 bash
> docker exec -it wp_mysql bash
root@dab19e479a65:/#
「root@dab19e479a65:/#」のように表示されれば、コンテナの中に入ることに成功。
MySQLの対話モードを起動する
コンテナに入ったら、まずはMySQLが存在するか確認する。
$ mysql –version でバージョン情報が表示されれば、MySQLがインストールされている。
root@dab19e479a65:/# mysql --version
mysql Ver 14.14 Distrib 5.6.51, for Linux (x86_64) using EditLine wrapper
バージョンが確認できたら、ルートユーザーとしてMySQLにログインする。(※注 docker-compose.ymlで指定したユーザーではない)
以下コマンドを実行。
$ mysql -u ルートユーザー名 -h ホスト名 -pパスワード
オプション | 内容 | 必要性 | デフォルト |
-u | ユーザー名 | 必須 | root |
-h | ホスト名 | 省略可(localhostとみなす) | localhost |
-p | パスワード | 必須 | root |
デフォルトの設定の場合
もし、MySQLの設定がデフォルトのままで、ルートユーザーの情報などを変更していない場合は以下の設定になっている。
- ルートユーザー名: root
- ホスト名: localhost ※省略可能
- パスワード: root
次のコマンドを実行すればルートユーザーとしてログインできる。
# mysql -u root -proot
以上でDocker上のMySQLコンテナの対話モードの起動が完了。これでSQLが実行できる。
ユーザーに権限を付与する
ルートユーザーとしてログインできたら、まずは、現在登録されているユーザーと権限を確認する。同時に確認できないので、ユーザーの一覧を確認してから、個別に権限を確認する。
ユーザーの一覧を確認
mysql> select user, host from mysql.user;
コマンドを実行するとユーザーの一覧が表示される。
+---------+-----------+
| user | host |
+---------+-----------+
| root | % |
| wp_user | % |
| root | localhost |
+---------+-----------+
3 rows in set (0.00 sec)
上記例では、rootユーザーと、wp_userの2つのユーザーが存在する。
なお、hostの「%」はワイルドカードで、すべてのホストを許容するという意味。
ユーザーの権限を確認
ユーザーの権限を確認するには、以下コマンドを実行する。
mysql> show grants for 'ユーザー名'@'ホスト名';
例えば、以下のようになる。
mysql> show grants for 'wp_user'@'%';
+--------------------------------------------------------------------------------------------------------+
| Grants for wp_user@% |
+--------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'wp_user'@'%' IDENTIFIED BY PASSWORD '******' |
| GRANT ALL PRIVILEGES ON `wp\_db`.* TO 'wp_user'@'%' |
+--------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
wp_userは「GRANT USAGE ON *.*」ですべてのDBに何も権限を与えない(USAGE)とした上で、「GRANT ALL PRIVILEGES ON ‘wp_db’」として、データベース名 wp_db のみ全ての権限を与えるとしている。
つまり、最初に作成した1つ目のDBしかアクセスする権限を持たないということ。次でこれを変更する。
(参考)MySQL公式 権限一覧
ユーザーの権限を変更する
ユーザー名と現在与えられている権限が確認できたので、次に、権限の変更を行う。
権限の変更・付与は「grant」コマンドを使う。ここでは、対象のユーザーにすべてのデータベースにアクセスする権限を付与する。
grant all privileges on *.* to 'ユーザー名'@'ホスト名';
実際の適用例は以下のようになる。
mysql> grant all privileges on *.* to 'wp_user'@'%';
Query OK, 0 rows affected (0.00 sec)
mysql> show grants for 'wp_user'@'%';
+-----------------------------------------------------------------------------------------------------------------+
| Grants for wp_user@% |
+-----------------------------------------------------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'wp_user'@'%' IDENTIFIED BY PASSWORD '******' |
| GRANT ALL PRIVILEGES ON `wp\_db`.* TO 'wp_user'@'%' |
+-----------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
グローバル「*.*」にすべての権限「ALL PRIVILEGES」を与えることができた。
これで、このユーザーでデータベースを作成することが可能になる。
grantコマンドと権限付与の設計
今回はすべてのデータベースにアクセスする権限を付与したが、対象のデータベースやテーブルを指定することも可能。
grantコマンドについてもう少し詳しく解説すると以下のようになる。
主な権限の種類
最初に指定する「与える権限名」には種類がかなりある。ここでは主要なもののみをご紹介。
権限名 | 内容 |
ALL PRIVILEGES | すべての権限 |
CREATE | DBやテーブルの作成 |
DROP | DBやテーブルの削除 |
DELETE | テーブルから行を削除 |
INSERT | テーブルに行を挿入 |
SELECT | SELECTコマンドの使用を許可 |
UPDATE | テーブルの行の更新 |
GRANT OPTION | 他のユーザーへの権限付与または削除 |
詳細は MySQL公式 権限一覧 にて。
<対象のDB>.<対象のテーブル>
- ワイルドカード「*」が使える。
- 「*.*」はすべてのDBのすべてのテーブルが対象。グローバルという。
- 「DB名.*」は、指定したDBの中のすべてのテーブルが対象。
identified by ‘<パスワード>’
identified by ‘<パスワード>’ の記述は省略可能。省略した場合はもともと設定してあるパスワードが適用される。
データベースを作成する
これまでの処理で、対象ユーザーにデータベースにアクセスする権限は付与できた。
しかし、データベース名が初回作成時と異なる場合は、そもそもMySQLに対象のデータベースが存在していないことになる。
この状態で、ブラウザをリロードすると「Unknown database ‘データベース名’」と表示されアクセスすることができない。
このため、対象のデータベースを作成しておく必要がある。(とても簡単で1分でできる)
MySQLのコンテナに入り対話モードで「database create データベース名」を実行する。
#現在作成されているデータベース一覧を表示
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| wp_db |
+--------------------+
4 rows in set (0.00 sec)
#データベースを新規作成
mysql> create database prograshi_db;
Query OK, 1 row affected (0.00 sec)
#確認
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| wp_db |
| prograshi_db |
+--------------------+
5 rows in set (0.00 sec)
これでデータベース周りの必要な設定は完了。
ブラウザをリロードする
ブラウザをリロードすると、いつものWordpressインストールの画面が表示される。
あとは、画面表示に沿って入力していけば、Wordpressサイトを起動することができる。
お疲れさまでした~