AWS ECSにSchemaSpyを乗せてサーバレスでER図を作成する

# TL;DR

公式のDockerを参考にしつつ `entrypoint.sh` の末尾にS3に吐き出す処理を書く

# 要件

- 任意の間隔でER図を定期的に生成したい
- ER図ドキュメントは特定のIPからのみアクセス可能にしたい
- EC2などサーバの面倒をみたくない。運用コストは最小限に。

# 流れ

今回は「ER図 自動生成」とかで検索するとヒットしやすいSchemaSpyを採用。特に深い理由は無いので好きなER図生成ツールを使う。ただしS3にアップロードする関係上静的ファイルを生成するツールを採用したほうが良い。

## dockerfile

S3に吐くためにawscliが必要だが公式のimageにはもちろんのこと入っていないので入れてあげる。

`entrypoint.sh` も自作のを使うのでCOPYする必要がある。

```dockerfile:Dockerfile
FROM schemaspy/schemaspy:snapshot

USER root

RUN apk --update --no-cache add \
    python \
    curl

RUN curl https://bootstrap.pypa.io/get-pip.py |python
RUN pip install awscli

COPY ./entrypoint.sh /

USER java

ENTRYPOINT ["/entrypoint.sh"]

```



## entrypoint.sh

ドキュメントを生成するまでは同じだが、生成されたドキュメントをS3にアップロードする処理を入れる必要がある。

```shell:entrypoint.sh
#!/bin/sh
export MAIN_CLASS=$(unzip -p schemaspy*.jar META-INF/MANIFEST.MF | grep Main-Class | awk -F ': ' '{sub(/\r/,"",$2);print $2}')
[ "$(ls -A /drivers)" ] && export DRIVER_PATH=/drivers/ || export DRIVER_PATH=/drivers_inc/
echo "Running Main-Class $MAIN_CLASS"
echo -n "With drivers:"
ls -Ax $DRIVER_PATH | sed -e 's/  */, /g'
java -cp *:$DRIVER_PATH* $MAIN_CLASS -o /output -t pgsql -host $DB_HOST -u $DB_USER -db $DB_NAME -p $DB_PASS
aws s3 rm $S3PATH --recursive
aws s3 cp /output $S3PATH --recursive
```

公式のentrypoint.shは

```shell
exec java -jar /usr/local/lib/schemaspy/schemaspy*.jar -dp $DRIVER_PATH -o $OUTPUT "$@"
```
となっており、java実行時に引数をすべて渡すようになっているが、S3にアップロード処理を書く際に汎用性とセキュリティの観点から環境変数で指定してあげるようにする。

```shell
java -cp *:$DRIVER_PATH* $MAIN_CLASS -o /output -t pgsql -host $DB_HOST -u $DB_USER -db $DB_NAME -p $DB_PASS
aws s3 rm $S3PATH --recursive
aws s3 cp /output $S3PATH --recursive
```

これで以下の環境変数を設定する必要が発生する。

- DB_HOST
- DB_USER
- DB_NAME
- DB_PASS
- S3PATH


s3を一度削除しているのはテーブル構成の変更で不要なファイルが発生することがあるため。

## ECR

何かとECSで動かす場合はECRに乗せたほうが幸せになるので乗せる

FIY
[Amazon ECR で AWS CLI を使用する - Amazon ECR](https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/ECR_AWSCLI.html)
[AWS CLI で Amazon ECR に docker イメージを push する - Qiita](https://qiita.com/aokad/items/17a06c2384041bd60d16)


例) er-documentsというリポジトリで作成していた場合

```shell
docker build -t er-documents .
aws ecr get-login --no-include-email --region ap-northeast-1  |bash -
docker tag er-documents:latest 000000000.dkr.ecr.ap-northeast-1.amazonaws.com/er-documents:latest
docker push 000000000.dkr.ecr.ap-northeast-1.amazonaws.com/er-documents:latest
```


## ECS

今回は常時起動ではなくスケジューリングで動かすので以下の記事を参考にタスクの定義まで行ってください

[Amazon ECS入門 〜公式のDockerイメージを使って10分で構築してみる〜 ｜ DevelopersIO](https://dev.classmethod.jp/cloud/aws/amazon-ecs-entrance-1/)
[AWS ECSでDockerコンテナ管理入門（基本的な使い方、Blue/Green Deployment、AutoScalingなどいろいろ試してみた） - Qiita](https://qiita.com/uzresk/items/6acc90e80b0a79b961ce)

タスクの定義が終わったらスケジューリングを行います
参考例を上げておきます

[Fargateがタスクスケジュールをサポートし定期実行処理の幅が超広がりました！ ｜ DevelopersIO](https://dev.classmethod.jp/cloud/aws/fargate-timebase-scheduling/)


<img width="1425" alt="スクリーンショット 2019-10-24 21.05.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45617/8133e82b-1b88-2a39-6427-228f466c57ab.png">


![screencapture-ap-northeast-1-console-aws-amazon-ecs-home-2019-10-24-21_07_43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45617/f4bb0845-9777-31f0-8873-c55920597b1b.png)


後は実行されるのを待てば完了です

<img width="1298" alt="スクリーンショット 2019-10-24 21.27.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45617/fdb83cde-f405-1d0a-6ba6-664df8b0f623.png">