1 Clickでエグゼクティブになるボタン

迫る年の瀬、寒いのは冬のせいか、懐のせいか、・・・
なにかと灰色の心持ちになるこの季節、ほのかなマッチにも似たアプリを作成しました。1 Clickで上場企業の役員になれるアプリです！その名も「エグゼクティブ・ボタン」。↓の画像をクリックすると起動します。

<a href="http://executive-loadbalancer-1470189009.ap-northeast-1.elb.amazonaws.com/" target="_blank">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25990/fa632141-9325-14b3-cca3-3309b1e5d2bb.png" width=500>
</a>

**エグゼクティブボタンのここがすごい!**

ボタンを押すだけで上場企業の役員報酬が手に入る！！

**エグゼクティブボタンのここがクソ!**

ほんとには手に入らない！！


実装はこちらです。

https://github.com/icoxfog417/executive_button

## 上場企業の役員報酬

2019年から、ガバナンス開示の一環として役員報酬などが公開されるようになりました。具体的には、有価証券報告書などの上場企業に義務付けられている開示文書へ記述するようになりました。

さらすのもはばかられますが、[弊社の役員報酬は以下のようになっています](https://www.tis.co.jp/documents/jp/ir/finance/securities_report/report_3103_4.pdf)。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25990/da45b9df-3835-e135-ff23-aebab160df4e.png)

一人頭4000万くらいですね。ふむ、なかなか・・・(あいまいな笑み)。この値は、PDFから読み取るという苦行を行わなくても取得が可能です。開示文書はXBRLというXMLを拡張した書式で書かれているため、XMLパースをすることでデータの取得が可能なのです。使われるタグは毎年改定があり、そのたび以下のように公表されています。

([2019年版EDINETタクソノミの公表について](https://www.fsa.go.jp/search/20190228.html))

役員報酬の総額は、「jpcrp_cor」という名称空間の「TotalAmountOfRemunerationEtcPaidByGroupRemunerationEtcPaidByGroupToEachDirectorOrOtherOfficer」というタグで取得可能です(長い)。名称空間は開示文書ごとに決められていて・・・と話していると長くなるので、興味がある方は[こちら](https://medium.com/programming-soda/%E8%B2%A1%E5%8B%99%E5%88%86%E6%9E%90%E3%81%AB%E6%AC%A0%E3%81%8B%E3%81%9B%E3%81%AA%E3%81%84-xbrl%E3%82%92%E7%90%86%E8%A7%A3%E3%81%99%E3%82%8B-part1-d4165fe0e84a)をご参照ください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25990/b42cca94-ea60-3355-0fcb-62a4de97c16c.png)

今回は、最近リリースした有価証券報告書などの文書と財務数値をまとめたデータセット「[CoARiJ](https://www.tis.co.jp/news/2019/tis_news/20191114_1.html)」を使用します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25990/3d1c5a3c-df80-6294-4d12-cc34f9f9e920.png" width=700>

CoARiJはテキスト情報と数値情報をセットで収録しているため、「良いこと言っているけど経営指標に反映されているのか」とか、「数値が悪いと環境活動(の報告)が控えめになるんじゃないか」といったテキスト/数値双方からの分析が可能です。今回はテキストの方に入っている役員報酬のデータを抜いてきて、それをアプリでランダムに表示するようにしています。

## アプリケーション構成

今回のアプリケーション、またインフラ構成は以下のようになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25990/002bcb20-c86f-6126-1028-ba80f126fd6e.png)

* アプリケーション構成
  * フロントエンド: [Nuxt](https://ja.nuxtjs.org/)
  * バックエンド: [Django Rest Framework](https://www.django-rest-framework.org/)
  * プロキシ: [Traefik](https://docs.traefik.io/) / 本番は[Nginx](https://nginx.org/en/)
* インフラ構成
  * GitHub Actionを使い、Docker imageをDocker Hubに登録/登録したimageを使用してFargateにデプロイ。

なんで開発と本番でプロキシが違うのか、には理由があります。

1. Traefikはホストの`docker.sock`へのアクセスを必要とするが、[Fargateではvolume bindができない](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/bind-mounts.html)。
2. Fargateでは`links`を使うことができないため、Nginxでホスト名の解決ができない。その代わり、[`localhost`で他コンテナにアクセスができる](https://qiita.com/taishin/items/84122ad85bedf8b8a682)。
3. よって、開発/本番双方でNginxを使う場合でも`nginx.conf`の値を変える必要がある(開発の時だと逆にlocalhostではアクセスできないのだ)。どのみち二重管理になるので、開発では設定が楽なTraefikを使用した。

こんな面倒ならプロキシを置かなきゃいいんじゃないの?と思いますがプロキシを置いているのには理由があります。
Nuxt/バックエンドでコンテナを分ける場合、Nuxtのサーバーサイドからのアクセスとクライアントサイドからのアクセス双方でプロキシが必要になります(詳細は[こちら参考](https://stackoverflow.com/questions/55090038/get-http-api1337-games-neterr-name-not-resolved-for-nuxt-js-pages-using-asy))。サーバーサイドについては、Nuxtのプロキシ設定で対応可能です。

```nuxt.config.js
  modules: [
    // Doc: https://axios.nuxtjs.org/usage
    "@nuxtjs/axios",
    "@nuxtjs/proxy"
  ],
  /*
   ** Axios module configuration
   ** See https://axios.nuxtjs.org/options
   */
  axios: {
    prefix: "/api",
    proxy: true
  },
  proxy: {
    "/api/": process.env.BACKEND_URL || "http://localhost:8000/"
  },
```

ただ、レンダリングされた後のJavaScript(クライアントサイドからのアクセス)はプロキシの設定なんてしりません。そのためホスト名が解消できないかクロスドメインエラーになります。クライアントサイドからのアクセスをバックエンドにきちんと伝えるには、リバースプロキシを置いて中継を行う必要があります。

Traefikは、このリバースプロキシの役割に適しています。Traefikの2.0系、docker-compose内にラベルを設定するだけでプロキシの設定が可能です。以下は公式のチュートリアルからの引用ですが、`whoami`のコンテナに`labels`で`Host`を設定するだけで、該当のホストへのリクエストを中継してくれます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25990/0602b742-8a0c-799a-7aa9-291748b1783b.png" width=600>

すごい便利！なんですが、前述のとおりホストの`docker.sock`を参照するためバインドが使えないFargateでは使えません。EC2に切り替えれば対応可能ですが、この時`AmazonEC2ContainerServiceforEC2Role`のポリシーが必要なことに注意してください([参考](https://stackoverflow.com/questions/36523282/aws-ecs-error-when-running-task-no-container-instances-were-found-in-your-clust))。

なお、FargateはデプロイするたびにPublic IPが変わってしまいます。このままでは大変なので、ロードバランサを前面においてリクエストを中継するようにします(なんか中継してばっかですが・・・)。ロードバランサの作り方については、以下が詳しいです。

[Run your container on AWS Fargate](https://itnext.io/run-your-containers-on-aws-fargate-c2d4f6a47fda)

`ecs-cli`から登録する場合は、`--load-balancer-name`(ロードバランサ)ではなく`--target-group-arn`(ターゲットグループ)で指定します。ロードバランサで指定すると、`Classic Load Balancers are not supported with Fargate`いわれました。


```
 ecs-cli compose service create \
       --target-group-arn "$ARN" \
       --container-name service_name_on_docker_compose \
       --container-port exposed_port
```

最終的なGitHub Actionを使ったデプロイについては、[リポジトリをご参照ください](https://github.com/icoxfog417/executive_button/blob/master/.github/workflows/dockerimage.yml)。

## 役員報酬ランキング

ええーい、とにかくどこの企業が多くもらってんのか教えてよ！という方のためにトップ10を作成しました。報酬が取得可能だった全1944社のうち、一人当たりの報酬が最も高いのが以下の企業です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25990/bfcb39ef-6b76-ae10-c62e-a13e9630a8bf.png)

東京エレクトロン株式会社で1,000万年はたらけば5000兆円手にはいりますね！(計算合ってる?)。全会社のデータはリポジトリにありますので、見てみてください。