【SchemaSpy】手間をかけずにRDS(MySQL)からER図を生成したい

## はじめに
RDSのデータ構造を確認するためにER図を作成したい。開発中にテーブルが増えていくので、簡単に作りたい。ということで、調べたら**SchemaSpy**というツールがあり、比較的簡単に生成・出力できることを知ったので、使ってみました。いろいろな方のSchemaSpyの記事を参考にさせていただきましたが、環境差異等もあり、いろいろつまずいたところもあったので、備忘録として残しておきます。

### 参考

下記の記事を参考にさせていただきました。

+ [まだER図の管理で消耗してるの？ SchemaSpy でER図を自動生成して管理する](https://qiita.com/ap8322/items/b93dfb2ff29b026ffa72)
+ [DockerでサクッとDBからER図を作成する](https://qiita.com/kamukiriri/items/ab1669c19831c18db9ee)
+ [DockerでサクッとDBからER図を作成する（MySQL 5.5.45+, 5.6.26+ and 5.7.6+）](https://qiita.com/miurabo/items/9cd5826db0018177db6d)

## SchemaSpyとは
DBに接続すると、DBのテーブルの定義内容を読み取って、素敵なUIのHTMLとして出力してくれるツールです。Java製のツールなのですが、Dockerイメージが公開されているので、導入が簡単です ♪
Dockerイメージ：https://hub.docker.com/r/schemaspy/schemaspy/

## ER図の生成
それではやってみたいと思います。

### 構成図

![SchemaSpy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546572/453a00c8-f58a-9948-a93f-7d33d333e881.png)

EC2 OS : Amazon Linux 2
DBの種類 : MySQL 5.7.22

RDSの操作用に踏み台EC2をたてています。このEC2にsshで接続して、RDSのデータ構造をER図にします。そして、ローカルで、生成されたHTMLを開きます。
本記事では、SchemaSpyを用いてのER図生成箇所にフォーカスしています。

### いざ生成
#### EC2にDockerのインストール

Dockerイメージを使ってSchemaSpyを使用するので、まずDockerのインストールから始めます。Dockerのインストールは「[AWS EC2インスタンスにdockerとdocker-composeをインストールして簡単なWEBサービスを立ち上げる方法](https://qiita.com/y-do/items/e127211b32296d65803a)」を参考にさせていただきました。

```sh
$ sudo yum install -y docker
$ sudo service docker start

# ec2-userがdockerコマンドを実行できるように、ec2-userをdockerグループに入れる
$ sudo usermod -a -G docker ec2-user
```
一度ログアウトして再ログインする。

```sh
# インストール確認
$ sudo docker info
```

#### SchemaSpy Dockerイメージの取得

```sh
$ docker pull schemaspy/schemaspy

# インストール確認
$ docker images
```

REPOSITORYに`schemaspy/schemaspy`が追加されていればOKです。

#### schema生成(失敗)

```sh

$ docker run -v "$PWD/schema:/output" --net="host" schemaspy/schemaspy:6.1.0 -t mysql -host ＜ホスト名＞:＜ポート＞ -db ＜DB名＞ -u ＜DBユーザ名＞ -p ＜DBパスワード＞ -connprops useSSL\\=false -s information_schema
```

上記のコマンドで生成を試みましたが、エラーが出てうまくいかなかったので、次のように対応しました。


##### 対応策1 パスワードを別定義
パスワードをダブルクォーテーションでくくらず、直接生成コマンドに書いたのが、上手くいかなかった一番の原因でした。特殊文字/予約語が入っていたりすると別の意味になってしまい、思わぬところでエラーになってしまうことがわかりました。

なので、`export`コマンドを使ってパスワードを環境変数に定義しました。

```sh

$ export DB_PASS="＜DBパスワード＞"
```

もしくは、生成コマンドに入れる際に、`-p "＜DBパスワード＞"`とダブルクォーテーションでくくるのでも大丈夫でした。この場合は環境変数に入れる上記のフローは不要です。

##### 対応策2 ディレクトリの作成
出力するために、下記のディレクトリを作成します。作成せずに生成すると、`ERROR - IOException Unable to create directory /output/tables`というエラーが出てしまいます。おそらく権限の問題かなと思います。ただ、このディレクトリには出力されたファイルを保存するわけではありません。

```sh

$ mkdir -p schema/output/tables
```

オプション`-p`を設定することで、`schema`、`output`、`tables`のディレクトリを一度に作成することができます。

##### 対応策3 schema生成

先ほどの[schema生成(失敗)](#schema生成失敗)では、オプション`-s`のあとに`information_schema`を指定しましたが、RDSを作成した際に作ったマスターDBユーザだと権限が足りないようです。なので、ER図を生成したいDB名を再度指定するようにしました。

```sh

$ docker run -v "$PWD/schema:/output" --net="host" schemaspy/schemaspy:6.1.0 -t mysql -host ＜ホスト名＞:＜ポート＞ -db ＜DB名＞ -u ＜DBユーザ名＞ -p ${DB_PASS} -connprops useSSL\\=false -s ＜DB名＞
```

先ほど`export`で外に出したパスワードは、`${DB_PASS}`で読み込むことができます。

これでカレントディレクトリに作成していた`schema`配下にファイルが作成されます。

#### ローカルにダウンロード
生成したファイルをローカルにダウンロードします。

```sh
# EC2内で実行
$ zip -r schema.zip schema
$ exit 

# ローカルで実行
$ scp -i "$HOME/.ssh/＜pemキー＞" ec2-user@＜IPアドレス＞:/home/ec2-user/schema.zip ./
$ unzip schema.zip
```

#### ER図の閲覧
`schema/index.html`を開くとDBの情報を見ることができます。素敵なUIです！

<img width="1440" alt="スクリーンショット 2020-06-06 14.17.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546572/dc3a269b-4bd2-7274-2250-9e7edfcc16e9.png">

<img width="1440" alt="スクリーンショット 2020-06-06 14.17.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546572/a4cdfb09-2da4-dbea-f8f6-7e6bf5f24eee.png">

## やっぱりローカルから生成したい
sshでEC2に接続して上記のコマンドを実行して、ローカルにコピーするのも、テーブルが増えるたびに実行するのは面倒なので、わたくし初めてシェルスクリプトを書いてみました！
2回目以降はDockerのインストールなどの準備は不要なので、そのあたりは省きます。

### 実装

```sh:ec2.sh
#!/bin/bash

set -e

# Dockerの起動
sudo service docker start

# DBパスワードの入力
echo -n DB_PASS:
read DB_PASS

# schema生成
docker run -v "$PWD/schema:/output" --net="host" schemaspy/schemaspy:6.1.0 -t mysql -host ＜ホスト名＞:＜ポート＞ -db ＜DB名＞ -u ＜DBユーザ名＞ -p ${DB_PASS} -connprops useSSL\\=false -s ＜DB名＞

# ファイルの圧縮
zip -r schema.zip schema

# Dockerの停止
sudo service docker stop

exit 0
```

上記のシェルスクリプトをEC2にコピーしておきます。

```sh

$ scp -i "$HOME/.ssh/＜pemキー＞" ec2.sh ec2-user@＜パブリックIP＞:/home/ec2-user/
```

ローカルには下記のシェルスクリプトを用意します。

```sh:local.sh
#!/bin/bash

set -e

# EC2のパブリックDNS、もしくはパブリックIPの入力
echo -n TARGET_EC2:
read TARGET_EC2

# EC2でec2.shをたたく
ssh -i "$HOME/.ssh/＜pemキー＞" ec2-user@${TARGET_EC2} 'bash /home/ec2-user/ec2.sh'

# ローカルにコピー
scp -i "$HOME/.ssh/＜pemキー＞" ec2-user@${TARGET_EC2}:/home/ec2-user/schema.zip ./
unzip schema.zip

# index.htmlを開く
open ./schema/index.html

exit 0
```

### 実行

```sh

$ bash local.sh
```

上記のコマンドをたたくと、EC2のパブリックIPとDBのパスワードの入力を求められるので、その2つを順番に入力していくだけで、ローカルから生成できるようになりました！
めでたしめでたし！！

## おわりに
SchemaSpyを使ってのER図の作成は、Dockerイメージの有り難さを感じつつ、簡単に作成することができました！
今後パスワードの書き方は気をつけます。

そして、初めてシェルスクリプトを書いてみました！
ssh接続からEC2内の操作まで書いたシェルスクリプトをローカルで実行すると、EC2にsshで接続でしたところでその後の操作が実行されず止まってしまいました。なので、ローカルで実行する部分とEC2内で実行する部分を分けることにしました。
上記のような操作だと、思ったより簡単に書くことができて、作業時間の短縮にもなるので、これからも活用していこうと思います！