ECS, Fargateで立てたサーバーをPrismaでRDSにつなぐ
使用技術
TS, Node(Hapi), Prisma, ECS, Fargate, RDS(MySQL)
現在既にAWS上でサーバーが起動しているものとする。
index.ts
import Hapi from "@hapi/hapi"; import { PrismaClient } from "@prisma/client"; const prisma = new PrismaClient(); const init = async () => { const server = Hapi.server({ port: 3030, }); server.route([ { method: "GET", path: "/", handler: () => { console.log("run"); return "Hello World!"; }, }, { method: "GET", path: "/users", handler: async () => { console.log("users"); const users = await prisma.user.findMany(); return users; }, }, ]); await server.start(); console.log("サーバー起動"); console.log("Server running on %s", server.info.uri); }; init();
schema.prisma
datasource db { provider = "mysql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" // ローカルでエラー起きたのでここ書いてる。いらないかも binaryTargets = ["native", "debian-openssl-1.1.x"] } model User { id Int @id @default(autoincrement()) name String? age Int? }
Dockerfile
FROM node:12 RUN apt-get update RUN apt-get install -y openssl WORKDIR /app COPY package*.json /app RUN npm install COPY . /app EXPOSE 3030 EXPOSE 5555 CMD npx ts-node src/index.ts
ローカルでは.envファイルやdocker-composeにDATABASE_URLを定義すればPrismaがそれを読み取ってくれる。だが、AWS上ではそのようなものを持たせてないので環境変数を別途AWS上で定義する。
方法はいくつかあると思うがSystems Managerを使うことにする。公式にも
Amazon ECS を使用すると、AWS Systems Manager パラメータストア パラメータに機密データを保存してコンテナの定義でそれを参照することによって、コンテナに機密データを挿入できます。
とあるのでECSとの相性は良さそう。
パラメータストアにパラメータを定義
Systems Managerという機能群の中の1つであるパラメータストアを使い実際に環境変数を定義していく。
↑ここから作成
ここでは sampleServerDatabaseUrl というキーで作成する
コンテナに環境変数を定義
作成したキーを実際にコンテナから使用する
タスク定義を修正する必要があるので対象のタスク定義から「新しいリビジョンの作成」をクリック。
現在のコンテナをクリックして、モーダルの下の方にある「環境変数」の部分で指定する。
この時、ValueFromを選択するよう気を付ける
使用するタスク定義の変更
最初に書いた通り、今回はすでにサーバーが動いている状態からの変更である。
先程タスク定義の新たなリビジョンを作成したが、サービスが使用しているタスク定義は依然として古いもののままである。
なのでサービスが使うタスク定義を最新のものに変更する
変更は↓から行うことができる
なお、ここで権限のエラーが出た場合
ECSからSystems Managerの値参照しようとしたらResourceInitializationErrorが出た - プログラミングとかのお雑な備忘録
を参照
Prismaでマイグレーション
今のままだとmigrateできてないのでする。DockerfileのCMDで行うことにする。CMDで複数コマンド実行したい場合は自分はシェルで定義しているのでここでもそうする。
start.sh
if [ "$NODE_ENV" = "development" ] then npx prisma migrate dev npx ts-node src/index.ts elif [ "$NODE_ENV" = "production" ] then npx prisma migrate deploy npx ts-node src/index.ts fi
Prismaは環境によってマイグレーション方法が prisma migrate dev とprisma migrate deployで別れるので環境変数NODE_ENVを定義して、その値で判断させることにする。
なのでまた「新しいリビジョンの作成」-> 既存コンテナクリック -> 環境変数のとこで追加する
ローカルでは.envファイルやcomposeなどにdevelopmentを定義
次に上記Dockerfileの
CMD npx ts-node src/index.ts
を
CMD ["./start.sh"]
に変更する。
権限を与えるため
chmod 744 ./start.sh
を実行
ECRの「プッシュコマンドの表示」に従い新たなImageをプッシュする。
タスク定義から「新しいリビジョンの作成」で先程プッシュしたImageのURIに更新。
サービスで使用するリビジョンを更新したバージョンに変更。
そうしてログを見てみると
こんな感じのエラーが出る。
セキュリティグループを修正してこのエラーに対応する。
セキュリティグループの修正
ECSとFargateとALBでNodeサーバーを立てる - プログラミングとかのお雑な備忘録
ここでも書いたのと同じような要領で修正セキュリティグループを修正していく。
まずサービスのセキュリティグループを確認。
ここではSample-6411
次にRDSのセキュリティグループを修正する。
[Eidit inbound rules]をから修正ページに入る。
↓このルールを追加
この中の選択されているグループは先程確認した Sample-6411
これで修正はOK
強制的に再デプロイして確認
↓強制的に再デプロイする方法
AWSコンソールでサービスを見つけます。 右上隅にある[更新]をクリックします。 [新しい展開を強制する]チェックボックスをオンにします。 他の構成をスキップして、[サービスの更新]をクリックします。 サービスは再デプロイされます。
<ALBのDNS>/users をブラウザのURL欄に打ち込んで確認
エラーが出ずに[]が帰って来れば無事成功!
TODO
DBは多分パブリックでアクセスできる必要ないのでプライベートにする。
プライベートバージョンからちゃんと接続できるか確認
Route53を用いた独自ドメインでの構築
参考
AWS ECS(バックエンド編)|Nuxt.js + Ruby on Rails + AWS Fargate の開発・デプロイチュートリアル
AWSの公式の記事色々