🕌

Graphql&Next.jsをFargate&TerraformにGitHub ActionからDeploy

2022/06/15に公開

この記事について

登山を趣味しているLaravelをメインに開発してきたwebエンジニアです。
業務でreactに触れたことでその便利さに感動して

  1. React Router
  2. Redux-toolkit
  3. Typescript
  4. Next.js
  5. Graphql

という流れでFrontendに惹かれていき、タイトルの通りGraphqlを使用したNext.jsをTerraformで構築したFargateにGitHub ActionからDeployを試みてみました。
ネットワークの構築も実務ではしたことがなく、Graphqlもどう使われるのか最初は実装しててもイメージが湧かなかったぐらいでしたが、試行錯誤の元deployに成功することができました。アプリケーションとしてはまだまだではありますが、deployに至るまでに参考にさせてもらった記事などをシェアして、参考になる方がいらっしゃれば嬉しいです。

ソース

登山計画を建てる際に、どういうルートでどういう時間配分で登るのかなどを調べる必要があるのですが、その都度色んなページを見なくては行けなかったり、登山道の崩落や登山道までの道路で土砂崩れなどによる迂回路情報、登山道までのバスやその乗り継ぎなど、全て別々のサイトで調べなければなりません。
どうにかして一度にそれらの情報が見れるサイトがあればとの思いで、自由にルートを作成できるサイトを作ってみました。

frontend
https://github.com/kaji0214/mt-route-app

  • Next.js
  • typescript
  • Prisma
  • TypeGraphQL Prisma
  • NextAuth.js
  • Apollo Client
  • graphql-codegen
  • docker
  • jest
  • React Testing Library
  • msw
  • storybook

infra
https://github.com/kaji0214/mt-route-infra

  • Terraform
  • ecspresso
  • Fargate

フロント開発の試み

失敗1

参考記事

使用技術

  • Next.js
  • Nexus
  • Prisma
  • Urql
  • redux-toolkit
  • npm

感想

Graphqlが便利と聞いていたので使ってみたものの、Nexusを使ってDefinitionを実装していても自分が何のために何をしているのか明確にイメージが湧きませんでした。詳細は他の記事を探して参照してもらえれば詳しい説明がいっぱいあるとは思いますが

  • Prismaがモデルを生成
  • Nexusがモデルを元に、取得できるモデルのフィールドや取得の仕方などのGraphqlとしてデータを晒すための設計書を定義

これによりAPIによって取得されたモデルのデータをどう取得するのかといった柔軟なqueryがGraphqlとして可能になります

失敗の原因 Nexusの使用

Nexusを選定したのは失敗でした。メンテナンスが追いついてなく、第三者によって開発されているnpm packageを使わないと動かなかったり、ソースを0から構築し直すと動作しなくなったり、いかに技術選定が大事なのか思い知りました。

失敗2

https://blitzjs.com/

使用技術

  • blitz

失敗の原因 技術選定のミス

色々動作しなくなってしまったこともあり、かつこの頃にはhttps://techblog.yahoo.co.jp/entry/2020121530052952/
yahooさんのこの記事を見たり、Graphql FragmentやGraphql Anywareの filterが便利などということも聞いていたこともあって、、全てまとめられているBlitz使ってGraphql使えばいいじゃんと思ったのですが、「gqlが使えないBlitzはなし」と開発は終わりました。技術選定の大事さ、そういえば即忘れていましたね・・・。

成功

  • Next.js
  • prisma
  • type-graphql
  • Graphql Fragment
  • codegen
  • Apollo Client
  • Context
  • yarn

理由1 Graphql Fragment

fragmentを使用することでcomponent単位で必要なデータが明確になり、かつpageで1つのqueryにまとめることで、1回リクエストするだけで済みます。

詳細

理由2 Context

元々redux-toolkitに慣れていましたが、それをtypescirptで書こうとすると行数も学習コストもcontextと比べると割に合わないと感じました。実際にcontextを使用することで、シンプルな実装になり、jestも書きやすかったです。

理由3 type-graphql

Nexusの代替 type-graphqlはちゃんとメンテナンスされていて、ドキュメントもまとまっているので、困ることがなかったです。

インフラ

「CI/CDの知識を深めたい」と漠然と思っていたところ「TerraformでFargateを構築してGitHub Actionsでデプロイ!Laravel編」という本当に有り難い書籍があり、「これ見ながらやれば出来るでしょ」と安易な気持ちで見た結果、ネットワークの知識が無さすぎて最初は頓挫致しました。読めるために学んだことを記していきます。

3分間ネットワーキング

http://www5e.biglobe.ne.jp/aji/3min/

「講座内容」の第0回から第81回を読みます。完璧に理解しようとしてモチベーションが下がることを懸念していたので分かりにくいことは簡単に深堀りして、そこで理解できなければ「今はレベルが適していない」と思うことにして一旦スルーしました。

Linuxで動かしながら学ぶTCP/IPネットワーク入門

https://www.amazon.co.jp/dp/B085BG8CH5/ref=cm_sw_r_tw_dp_ENH1HCN3NKM9PD4RYQDD
「3分間ネットワーキング」を読むだけだと具体的なイメージが湧かなかったので、実際に動作確認をして理解を深めるためにこの書籍を選ばせて頂きました。
パソコン1つで実際にネットワークの動きを確認できたので、とても参考になります。

TerraformでFargateを構築してGitHub Actionsでデプロイ!Laravel編

上2つを読むことで、やっとFargateに手を出せるようになりました。
デプロイまで行けた現在でも、書籍の内容を全てを理解出来ている訳ではなく、見様見真似の部分もあるのですが、実際にGithub actionが成功したときは、燕岳登頂並の達成感がありました。

補足

ssmを使うタイミング

「TerraformでFargateを構築してGitHub Actionsでデプロイ!Laravel編」では、Github action内でFargate上でのmigrationの実行とFargateへのデプロイが以下のコードで実行されています
https://github.com/shonansurvivors/laravel-fargate-app/blob/de9fe9621c47cb2b07ce709555ec4d6439e4b255/.github/workflows/deploy.yml#L106-L116

migration時もデプロイされたアプリケーションも参照するsecretなenv変数はssmから参照されますが、Next.jsは.envファイルから参照されるので、ssmからは値があっても参照されませんでした。
今回の場合Github ActionではNext.jsがdeployされるFargateのタスク上でprismaのmigrationが実行されることなりますが、このときprismaを動作させるだけなので.envファイルは読み込まれず、env変数はssmから参照されます。よってprismaのschemaで

datasource db {
  provider = "mysql"
  url      = env("DB_URL")
}

のようにenvでデータベースのURLが指定されている場合は、このenvがssmに登録されている必要がありました。

mswがtypescriptに対応していた

便利過ぎます
https://www.graphql-code-generator.com/plugins/typescript-msw

useCallbackとuseMemoを理解するためのおすすめ記事https://medium.com/@jan.hesters/usecallback-vs-usememo-c23ad1dc60

感想

インフラ構築ってこんなに大変なんですね・・・
そしてFargateは最小構成でも一日7.34$かかってびっくりしました。即サービス止めてしまったのですが、serverlessなどにデプロイして安く抑えつつ、今後運用していければと思っています。

今後したいこと

  • バスのルートや運行表の取り込みや表示機能の実装
  • 海外対応
  • 登山ルートをさらに細分化し、コースの詳細情報や危険箇所などの表示機能の実装

試してみたい技術

  • amplify
  • PostGIS
  • nestjs
  • firebase

以上です。ありがとうございました。

Discussion