
Prisma CLIを使ってTerraformで作成したRDSを管理してみた
こんにちは。クラウド事業本部の桑野です。
前回、ColimaとDockerでAWSリソースをデプロイできるTerraformコンテナを構築しました。
今回はコンテナ環境を使ってTerraformでRDSを用意し、Prisma CLIでマイグレーションやシードをやってみました。
普段TypeScriptで開発されてる方なら、意外と簡単にRDSの管理が出来ちゃいます。
前回の記事
Prismaとは
Next-generation Node.js and TypeScript ORM
Prisma ORM unlocks a new level of developer experience when working with databases thanks to its intuitive data model, automated migrations, type-safety & auto-completion.
Node.jsとTypeScriptのORM(Object-Relational Mapping)です。
直接SQLを書くのではなく、オブジェクトのようにデータベースを操作する仕組みを提供しています。
独自のスキーマ定義によってTypeScript内での型安全・自動補完機能が便利で、マイグレーションやシードもできます。
今回はORMではなく、CLI(マイグレーションやシード機能など)を取り上げます。
構成内容
下記の構成をTerraformで構築し、RDSの管理をPrisma CLI(TypeScript)で行います。
- Terraform、およびPrisma CLIはそれぞれDockerコンテナから実行する
- Prisma CLIによるマイグレーション、シードはAWS CLI SSM Start SessionでEC2インスタンスを踏み台経由で接続・実行する
- データソースはAmazon RDS for MariaDBを使用
補足
構築するインフラがデュアルスタック構成になっていますが、今回の場合あまり意味はありません。
将来的にSSMエンドポイントがIPv6対応され、VPCエンドポイントを置かなくてもよくなるという期待を込めてそのようにしました。
検証しようとした記事が他にありますので、そちらもご覧いただければ幸いです!
前提
前回の記事同様、下記の条件で検証しています。
構築手順についてはそちらをご参照ください。
- OS:macOS Sequoia バージョン 15.6.1
- チップ:Apple M4
- Docker Client:28.4.0
- Docker Server:28.3.3
- Colima:0.8.4
- docker compose:2.39.3
また、Terraform実行用にAWS CLIのプロファイルが必要になります。
IAMユーザーのクレデンシャルを指定するので、あらかじめアクセスキーとシークレットアクセスキーを発行しておきましょう。
構築
コードは下記GitHubリポジトリにて公開しています。
1. AWS CLIのセットアップ
terraform_runner
というコンテナにアクセスします。
このコンテナではAWS CLIやTerraformが使用できます。
まずはaws configure
を実行し、事前に用意していたクレデンシャルを設定します。
今回はコード上でrds-prisma
と記述していますので、それに合わせて下記コマンドを実行していただければOKです。
aws configure --profile rds-prisma
2. Terraform実行
クレデンシャルの設定が完了したら、Terraformを使用して構成図のリソースを作成します。
cd /terraform-runner/terraform/environments/dev
terraform apply
3. Backend環境のセットアップ
次にbackend
というコンテナにアクセスします。
このコンテナでは、node22.20.0をベースにAWS CLI, SSMプラグインのインストールを行なっています。
アクセスができたら、下記のコマンドを順に実行し、必要なパッケージをインストールしましょう。
cd /backend/typescript/
pnpm install
パッケージのインストールが完了したら、いよいよPrismaのセットアップを行なっていきます。
4. Prisma CLIのセットアップ
まずは必要な環境変数を設定していきます。
/backend/typescript/environments
に.env.example
があります。
それをコピーし、.env.dev
を作成しましょう。下記のコマンドを実行すれば一発です。
cp /backend/typescript/environments/.env.example /backend/typescript/environments/.env.dev
中身はこんな感じです。
ここで設定するのは二つです。
- DB_SECRET_NAME
- DB_NAME
両方ともAWSマネジメントコンソールから確認していきます。
DB_SECRET_NAME
はSecrets Managerの赤枠内の文字列を、
DB_NAME
はRDSのダッシュボードからprisma-rds-manager-dev-rds
を選び、設定タブ赤枠内の文字列を
それぞれ設定します。
設定ができたら下記のコマンドを実行します。
実行すると/backend/typescript/prisma/models
内のprismaファイルで定義したモデル情報が型として生成されます。
cd /backend/typescript/
pnpm prisma:generate:dev
このカスタムコマンドは/backend/typescript/scripts/prisma/generateClient.ts
をtsxで実行しています。
処理の内容としては「任意のenvファイルを読み込み、prisma generate
を実行する」というものです。
これにより、stageやproductionなど複数の環境があっても、コマンドに渡す引数を変えるだけで柔軟に対応できるようにしています。
5. Prisma CLIの実行
型情報が生成できたら、Prismaを使ってDBにアクセスしていきます。
踏み台EC2への接続
まずはRDSと通信できる状況を用意します。
今回はssm start session
コマンドを用いて、ポートフォワードの仕組みにより、EC2を踏み台にRDSに安全に接続する方法で用意します。
VSCodeをお使いの方であれば、画面右上「タスクの実行...」からRDS: Start SSM Port Forward
というタスクを選択することで、ウィザードに従って情報を入力するだけで簡単にコマンドを実行できます。
ここでは下記の通り入力が求められます。
- AWSプロファイル名
手順1で設定したプロファイル名rds-prisma
を入力します。 - 踏み台に使用するEC2インスタンスのID
AWSマネジメントコンソールから確認します。
EC2を開き、prisma-rds-manager-dev-ec2-bastion
のIDを入力します。
- RDSのエンドポイント
こちらもAWSマネジメントコンソールから確認します。
RDSを開き、prisma-rds-manager-dev-rds
のエンドポイントを入力します。
- RDSのポート番号
デフォルトで3306を設定しています。今回は変更しないでください。 - ローカルのポート番号
こちらもデフォルトで3306を設定しています。今回は変更しないでください。
入力が完了するとコマンドが実行されます。成功していれば、ターミナル上にWaiting for connections...
が出力されます。
下記コマンドをターミナルから直接実行いただいても大丈夫です。
# ${}の部分は上記パラメータの通り置き換えて実行してください。
aws ssm start-session --profile ${input:awsProfile} --target ${input:ec2InstanceId} --document-name AWS-StartPortForwardingSessionToRemoteHost --parameters '{"host":["${input:rdsEndpoint}"],"portNumber":["${input:rdsPort}"],"localPortNumber":["${input:localPort}"]}'
これでPrismaとRDSを接続する準備は整いました。
マイグレーションファイルの作成
下記コマンドを実行します。
cd /backend/typescript/
pnpm prisma:migrate:create:dev
現在のPrismaで定義されているスキーマでマイグレーションファイルを作成するのですが、実行中に下記のようにマイグレーションファイルにつける名前を入力するよう求められます。
? Enter a name for the new migration: ›
生成されるマイグレーションファイルにはyyyyMMddhhmmss_
がプレフィックスとして付与されます。
命名はなんでも良いのですが、基本的にはDBに加える変更内容が一目でわかるようにするのが良いとされています。
今回はinit
と入力して作成しましょう。
実行するとtypescript/prisma/migrations
にyyyyMMddhhmmss_init
というディレクトリが出来上がっています。
中にはmigration.sql
があり、マイグレーションで適用されるSQLが定義されています。
-- CreateTable
CREATE TABLE `todos` (
`id` VARCHAR(191) NOT NULL,
`title` VARCHAR(255) NOT NULL,
`description` TEXT NULL,
`completed` BOOLEAN NOT NULL DEFAULT false,
`priority` ENUM('LOW', 'MEDIUM', 'HIGH', 'URGENT') NOT NULL DEFAULT 'MEDIUM',
`dueDate` DATETIME(3) NULL,
`createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`updatedAt` DATETIME(3) NOT NULL,
INDEX `todos_completed_idx`(`completed`),
INDEX `todos_priority_idx`(`priority`),
INDEX `todos_dueDate_idx`(`dueDate`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
今回はTODOを管理するテーブルをサンプルとして作成します。
ちなみにスクリプトで実行しているのは、下記コマンドです。
prisma migrate dev --create-only --schema=./prisma
--create-only
というオプションが重要で、これを明示することによって、マイグレーションファイルの作成のみを行うようにしています。
このオプションがない場合、Prismaはマイグレーションの作成と適用をセットで実行します。
下記のリスクが伴うため、仮に開発環境であったとしても--create-only
をつけることを推奨します。
- 意図しないマイグレーションの即時適用
マイグレーションファイルの内容をレビューする前に、データベースに変更が適用されてしまいます - データ損失のリスク
1によって既存のテーブルやカラムの変更・削除が実行されます。
バックアップがない場合、ロールバックが困難、もしくは不可能になってしまう可能性があります。 - サービスのダウンタイム発生
想定外のスキーマ変更が起こった場合、アプリケーションが動作しなくなる可能性があります。
大規模なマイグレーションであればあるほど、起こった場合のインパクトが大きくなります。
詳細については下記のドキュメントをご参照ください。
マイグレーションを適用する際は、事前にマイグレーションファイルの中身に問題がないか確認していただけると良いかと思います。
変更内容に問題ないことが確認できれば、RDSに対してマイグレーションを適用していきます。
マイグレーションの適用
下記コマンドを実行します。
cd /backend/typescript/
pnpm prisma:migrate:deploy:dev
All migrations have been successfully applied.
というメッセージが出力されればOKです。
現在のテーブルの状態がどうなっているかもPrismaのStudioという機能で簡単に確認ができます。
cd /backend/typescript/
pnpm prisma:studio:dev
ブラウザ上でTodo
テーブルが確認できます。
RDSは作成したばかりで、今はまだデータがありません。レコード数は「0」になっています。
シードの機能を使えばデータを一括で登録することができるため、次はシードを実行していきます。
シード
cd /backend/typescript/
pnpm prisma:seed:dev
実行が完了したら、Studioで見てみましょう。
レコードが8件に増えていることが確認できます。
以上で一通り、マイグレーションの作成・適用、シード、DBレコードの確認という主要な機能を試していただきました。
6. AWSリソースの削除
今回作成したリソースは、放っておくとお金がかかり続けます。
実施が終わったあと、リソースを残しておく必要がなければ削除することを忘れずに行なっておきましょう。
terraform_runner
コンテナにアクセスし、下記コマンドを実行します。
terraform destroy
以上で終了となります。お疲れ様でした!
まとめ
RDSへの通信経路が確立していれば、Prismaで簡単にマイグレーションやシードができます。
DBの変更履歴が自然と残るため、管理することを考えた際には強力な選択肢になると考えています。
「Prismaについて」で少し触れましたが、TypeScriptで開発をするのであれば、Prisma Clientを組み合わせることで、定義したスキーマが自動で型として反映され、オブジェクト指向的にデータベースにアクセスできます。
型補完を活用しながら安全にDB操作が可能です。
今後、Prisma Clientを使ったORM実装も取り上げていければと思います。
最後までご覧いただきありがとうございました!