Ubuntu + Node.js + Express の環境から、外部DB(MySQL)へ接続しデータを表示する

[前回、Expressの環境は作った](https://qiita.com/bonkoturyu/items/eaf6f1927f6a547fcf58)ので、その環境で作業する。

## MySQL をインストールする
Expressの環境にMySQLデータベースを置くんじゃなくて、参照用に必要。

```bash
npm install mysql --save
```

## test.js を作る

app.js 作ってたフォルダ内で、test.js を作る

```javascript:test.js
const mysql = require('mysql');

const con = mysql.createConnection({
  host: '192.168.123.223',
  user: 'root',
  password: 'root',
  database: 'test_database'
});

con.connect((err) => {
  if (err) throw err;
  console.log('Connected');
  con.query('select * from test_table', function (error, results, fields) {
    if (error) throw error;
    console.log(results[0]);
  });
});
```

### node.js で実行

- node test.js を起動

うまく接続出来れば、↓のようになるはず。

```
$ node test.js
Connected
RowDataPacket {
  id: 1,
  name: 'TOM',
  created_at: 2020-02-05T15:00:00.000Z,
  updated_at: 2020-02-05T15:00:00.000Z
}
```

- 接続できなくてエラーになった場合
  - Vagrantfile に `config.vm.network "private_network", ip: "192.168.123.223"` が記載されているか？
  - 特に Vagrantfile をいじくって無ければ、この設定だけで接続できる。
     - Vagrantfile については、[コレ](https://qiita.com/bonkoturyu/items/fcef25c7318beaa64d2d)を参照してください。
     - VirtualBox の設定で言うと、「NAT」と「ホストオンリーアダプター」の２種類のネットワーク設定が必要
- ER_NOT_SUPPORTED_AUTH_MODE が出て先に進まないよ！
  - アカウントに対しての権限？がMYSQL8.0で変わったらしい？
    - Node.jsにはまだ未実装だとか。
      - 実装済なのかもしれないが、現時点で出たので書いておく
      - なのでデフォルトから変更する
         - 使い方が違うかもしれないが、今回は気にしない
         - もちろん AUTH_MODE じゃなくなる
         - 実際にはセキュリティ低下だから注意
         - テスト環境なら気にしなくていいけどね
  - だから、権限を変えよう 

### 権限を変える 
ER_NOT_SUPPORTED_AUTH_MODE が出て先に進まないよ！
ってなってる人だけがやる作業。

MySQLにログインする

- ここでログインするのはデータベースのあるPCの方
  - Express の環境じゃなく、外部DB(MySQL)のデータがあるPC

##### MySQLに接続

mysql_host は、 docker-compose.yml の container_name と同じのにする。

```bash
$ docker exec -it mysql_host bash
```

接続できると、以下みたいな出力になる。
(root@の後ろはコンテナIDなので同じにはならないはず)

```
root@ff7eb30d5b23:/#
```

MySQLにログインして、データベースが出来てるか確認しよう
ユーザー名とパスワード入力

```
mysql -uroot -p
```

##### 使うデータベースを指定する
use test_database; を実行する。
↓こんな感じ

```
mysql> use test_database;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql>
```

##### 権限を確認する

多分こんな感じになってるはず。

```
mysql> SELECT Host, User, plugin from mysql.user;
+-----------+------------------+-----------------------+
| Host      | User             | plugin                |
+-----------+------------------+-----------------------+
| %         | docker           | caching_sha2_password |
| %         | root             | caching_sha2_password |
| localhost | mysql.infoschema | caching_sha2_password |
| localhost | mysql.session    | caching_sha2_password |
| localhost | mysql.sys        | caching_sha2_password |
| localhost | root             | caching_sha2_password |
+-----------+------------------+-----------------------+
6 rows in set (0.00 sec)
```

この plugin の caching_sha2_password というのが、今回のエラーの原因。
こいつを変更する。docker と root だけ。ほかは変えなくていい。

##### 権限を変更する

パスワードは自分の環境のものを入力してね。

まずは docker の分。

```
mysql> ALTER USER 'docker'@'%' IDENTIFIED WITH mysql_native_password BY 'your_password';
Query OK, 0 rows affected (0.03 sec)
```

次に root の分。

```
mysql> ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'your_password';
Query OK, 0 rows affected (0.00 sec)
```

```
mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password';
Query OK, 0 rows affected (0.02 sec)
```

これで変更出来た。確認する。

```
mysql> SELECT Host, User, plugin from mysql.user;
+-----------+------------------+-----------------------+
| Host      | User             | plugin                |
+-----------+------------------+-----------------------+
| %         | docker           | mysql_native_password |
| %         | root             | mysql_native_password |
| localhost | mysql.infoschema | caching_sha2_password |
| localhost | mysql.session    | caching_sha2_password |
| localhost | mysql.sys        | caching_sha2_password |
| localhost | root             | mysql_native_password |
+-----------+------------------+-----------------------+
6 rows in set (0.00 sec)
```

問題なく、 plugin が mysql_native_password に変わった。
これで接続できるはず。

## app.js を修正する
[前回](https://qiita.com/bonkoturyu/items/eaf6f1927f6a547fcf58)作った app.js を修正して、MySQLのデータを参照する

```javascript:app.js
var express = require('express');
var app = express();

var mysql      = require('mysql');
var connection = mysql.createConnection({
  host     : '192.168.123.223',
  user     : 'root',
  password : 'root',
  database : 'test_database',
  debug    : false,
});

app.get('/', function (req, res) {
  connection.connect();
  connection.query('select * from test_table', function (error, results, fields) {
    if (error) {
      connection.end();
      throw error;
    }
    res.send(results[0]);
  });
  connection.end();
});

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});
```

### node.js で実行

- node app.js を起動

実行すると、コンソールにはコレが出る

```
Example app listening on port 3000!
```

ブラウザで、 http://192.168.123.223:3000 にアクセスすると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194966/1ab6e9b4-7405-1366-ab21-0c5f652e1585.png)
こんなのが出るはず。

これで、ようやくExpressからMySQLへ接続し、データが参照できるようになった。


# 参考
- Check! mysqlのDockerコンテナにアクセスすると ER_NOT_SUPPORTED_AUTH_MODE エラーが出てしまうときの対処
  - https://qiita.com/dz_/items/ae7a0e5aad0ec9dd8ba7