Docker でサクッと MySQL 8 からER図を作成する

[DockerでサクッとDBからER図を作成する](https://qiita.com/kamukiriri/items/ab1669c19831c18db9ee) この記事を見て試してみようと思ったのですが MySQL 8 だとサクッとできなかったので試行錯誤のメモ。

なお、同じ Docker Desktop (Docker for Windows)の docker-compose で動いている MySQL から、同じホストで schemaspy コンテナを実行してER図を作成しようとしています。なので `--net` には docker-compose によって作られるネットワーク名を指定します。

---

```sh
docker run --rm --net hoge_default -v "$PWD/schema:/output" \
    schemaspy/schemaspy:snapshot -t mysql -host mysql:3306 -db hoge -u root
```

以下のようなエラーになりました。

> WARN  - Connection Failure
> Failed to connect to database URL [jdbc:mysql://mysql:3306/hoge] Unknown system variable 'query_cache_size'

MySQL の JDBC ドライバのバージョンを上げれば解決するとのことなので、次のように JDBC ドライバをダウンロードし、

```sh
mkdir -p drivers
curl -L https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-8.0.16.tar.gz |
    tar xvzf - -C drivers --strip=1 mysql-connector-java-8.0.16/mysql-connector-java-8.0.16.jar
```

ドライバを保存したディレクトリを `/drivers` にマウントして実行します。

```sh
docker run --rm --net hoge_default -v "$PWD/schema:/output" -v "$PWD/drivers:/drivers" \
    schemaspy/schemaspy:snapshot -t mysql -host mysql:3306 -db hoge -u root
```

今度は次のようなエラーになりました。

> ERROR - Bad config                                                                                                       
> Schema (-s/-schemas) was not provided and unable to deduce schema, schema is sometimes referred to as user/owner/database

`-s` でスキーマを指定して、とのことです。データベース名と同じものを指定すれば大丈夫そうです。

```sh
docker run --rm --net hoge_default -v "$PWD/schema:/output" -v "$PWD/drivers:/drivers" \
    schemaspy/schemaspy:snapshot -t mysql -host mysql:3306 -db hoge -u root -s hoge
```

次は以下のようなエラーになりました。

> ERROR - IOException                      
> Unable to create directory /output/tables

ディレクトリが作成できないとのことです。schemaspy は一般ユーザーで実行されるようにイメージが作成されているためのようです。次のように出力先ディレクトリを 777 にするか、

```sh
sudo mkdir -p schema
sudo chmod 777 schema
```

あるいはコンテナを root で実行すれば OK です。

```sh
docker run --rm --net hoge_default -v "$PWD/schema:/output" -v "$PWD/drivers:/drivers" -u root:root \
    schemaspy/schemaspy:snapshot -t mysql -host mysql:3306 -db hoge -u root -s hoge
```

Gitlab CI に仕込もうとするとイメージで指定されている USER を上書きできなさそうで無理そうでした。`schemaspy/schemaspy:snapshot` をベースに別にイメージを作成するのが良さそうです。

```sh
FROM schemaspy/schemaspy:snapshot

# USER を root にする
USER root

# mysql コマンドを使うために追加
RUN apk add --no-cache mysql-client

# JDBC ドライバをインストール
ADD http://search.maven.org/remotecontent?filepath=mysql/mysql-connector-java/8.0.16/mysql-connector-java-8.0.16.jar \
    /drivers/mysql-connector-java-8.0.16.jar

# Gitlab CI のためにエントリポイントをクリア
ENTRYPOINT [""]

# schemaspy の実行コマンドを配置
COPY schemaspy.sh /usr/local/bin/schemaspy
RUN chmod +x /usr/local/bin/schemaspy
```

`schemaspy.sh` は次のような内容です。

```sh
#!/bin/sh
exec java -cp '/*:/drivers/*' org.springframework.boot.loader.JarLauncher "$@"
```

次のように使えます。

```yaml
schemaspy:
  stage: build
  image: registry.gitlab.example.com/ore/hoge/schemaspy
  only:
    - master
  services:
    - name: mysql:8
      alias: mysql
      command:
        - --default_authentication_plugin=mysql_native_password
  dependencies:
    - dump
  script:
    - zcat build/dump.gz.sql | mysql -u root hoge
    - schemaspy -o build/schema/ -t mysql -host mysql:3306 -db hoge -u root -s hoge
  artifacts:
    paths:
      - build/schema/
    expire_in: 1 days
```

別のジョブ `dump` でマイグレーションを実行して `mysqldump` したものをアーティファクトにして `schemaspy` ジョブでそれをインポートしてから `schemaspy` を実行しています。