導入
前回の記事(というか、さっき書いた記事)
「そのうち」といったのですが、このネタを年を跨いで書くのはなんかアレなので、早速コンテナー版MySQL Server 8で試すことにしました。 前回の記事で何をやっているのかは説明したので、今回はコマンドの羅列で失礼します。
% docker container run -d --name some-mysql8 -e MYSQL_USER=root -e MYSQL_ROOT_PASSWORD=my-secret-pw -e MYSQL_PASSWORD=my-secret-pw -p 53306:3306 docker.io/mysql/mysql-server:latest % docker exec -it some-mysql8 mysql -uroot -p mysql> CREATE USER 'nodejsuser'@'localhost' IDENTIFIED BY 'my-secret-pw'; mysql> GRANT all ON *.* TO 'nodejsuser'@'localhost'; mysql> ALTER USER 'nodejsuser'@'localhost' IDENTIFIED WITH mysql_native_password BY 'my-secret-pw'; mysql> FLUSH PRIVILEGES; mysql> CREATE DATABASE list_app; mysql> USE list_app; mysql> CREATE TABLE users (id int, name varchar(10)); mysql> INSERT INTO users VALUES (1,'Yamada'); mysql> INSERT INTO users VALUES (2,'Tanaka'); mysql> INSERT INTO users VALUES (3,'Suzuki');
IPアドレス、ポートなどを修正して実行してみると...エラーメッセージが表示されます。 なるほど、docker0のゲートウェイIPアドレスですね。
$ node mysql.js
/Users/ytooyama/working/nodejs/mysql.js:13
if (error) throw error;
^
Error: Access denied for user 'ytooyama'@'172.17.0.1' (using password: YES)
at Packet.asError (/Users/ytooyama/working/nodejs/node_modules/mysql2/lib/packets/packet.js:728:17)
at ClientHandshake.execute (/Users/ytooyama/working/nodejs/node_modules/mysql2/lib/commands/command.js:29:26)
at Connection.handlePacket (/Users/ytooyama/working/nodejs/node_modules/mysql2/lib/connection.js:456:32)
at PacketParser.onPacket (/Users/ytooyama/working/nodejs/node_modules/mysql2/lib/connection.js:85:12)
at PacketParser.executeStart (/Users/ytooyama/working/nodejs/node_modules/mysql2/lib/packet_parser.js:75:16)
at Socket.<anonymous> (/Users/ytooyama/working/nodejs/node_modules/mysql2/lib/connection.js:92:25)
at Socket.emit (node:events:390:28)
at addChunk (node:internal/streams/readable:315:12)
at readableAddChunk (node:internal/streams/readable:289:9)
at Socket.Readable.push (node:internal/streams/readable:228:10) {
code: 'ER_ACCESS_DENIED_ERROR',
errno: 1045,
sqlState: '28000',
sqlMessage: "Access denied for user 'nodejsuser'@'172.17.0.1' (using password: YES)",
sql: undefined
}
ちょっと脱線
DockerでMySQLをコンテナーで動かす場合、外からのアクセスはポートバインドで許可すると思います。
Dockerのデフォルトではdocker0というインターフェイスがあって、これが172.17.0.1/16のIPアドレスになっています(ちなみに172.17.0.0/16のネットワークが使われていると判断されると、第2オクテットの数字を1つ加えてdocker0のIPアドレスが設定され、コンテナーにはそのネットワークからIPアドレスを割り当てます。以降同様に使われていないネットワークでデフォルトネットワークが構成される)。
DockerをLinuxで動かしている場合はip addrとかifconfigコマンドでdocker0を確認できると思いますが、Docker for macの場合は次のように実行してVMにログインするとそのシェル上でdocker0のIPアドレスを確認できます。
$ docker run -it --rm --privileged --pid=host busybox nsenter -t1 -m -u -i -n
結論
話を戻して、つまり今回の場合は、'nodejsuser'@'172.17.0.1'からのアクセスを許可する必要があるということみたいです。 以下のように実行します。
mysql> CREATE USER 'nodejsuser'@'172.17.0.1' IDENTIFIED BY 'my-secret-pw';
mysql> GRANT all ON *.* TO 'nodejsuser'@'172.17.0.1';
mysql> ALTER USER 'nodejsuser'@'172.17.0.1' IDENTIFIED WITH mysql_native_password BY 'my-secret-pw';
mysql> FLUSH PRIVILEGES;
...
$ node mysql.js
[
{ id: 1, name: 'Yamada' },
{ id: 2, name: 'Tanaka' },
{ id: 3, name: 'Suzuki' }
]
これでようやくコンテナでMySQLを使えるようになったかも。