導入
前回の記事(というか、さっき書いた記事)
「そのうち」といったのですが、このネタを年を跨いで書くのはなんかアレなので、早速コンテナー版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を使えるようになったかも。