🌏

できるだけシンプルにPrismaをLambdaで動かす

2024/05/29に公開

モチベーション

Prismaのドキュメント「Deploy to AWS Lambda」にはPrismaをLambdaで動かすための手順に関して説明がありますが、AWS SAM、Serverless Framework、SSTなどのツールを使うケースについてのみ記載されており、いずれのツールも使いたくない時にどのような条件を満たせば良いのかが読み取れませんでした。そこで本記事では、なるべく依存するツールを最小限にして、Lambda上でPrismaが動作するための条件を整理していきます。

要約

はじめに要約です。一つ一つの見出しだけでも独立した記事にできそうなほど手順が多いですが、この記事のポイントは以下の3つです。

  1. binaryTargetsにLambda実行環境に合わせたQuery Engineの設定を行う
  2. Query Engineを含めてzipファイルを作成する
  3. PRISMA_QUERY_ENGINE_LIBRARYにQuery Engineファイルのパスを指定する

Query Engineについてはこちらのドキュメントを参照してください。

前提条件

  • Lambdaにデプロイするアーティファクトの作成はesbuildで行う。
  • Lambdaの実行環境はNode.js 20.x、アーキテクチャはx86_64。
    • 後述の通り、Node.js 16.xや18.x、arm64アーキテクチャの場合、Query Engineファイル名が異なります。
  • Lambda関数の作成は手動で行い、IaCツールは使わない。
    • CDKで構築しても良いのですが、設定の本質が見えづらくなるので今回は割愛。
  • Lambda Layer、RDS Proxyは使わない。
    • 設定の本質が見えづらくなるので今回を割愛。

AWS CLIおよびesbuildを使用したLambdaへのTypeScriptコードのデプロイ

まずはAWSの公式ドキュメントに沿ってデプロイ対象のアプリケーションを構築します。以下のようなコマンドでビルドできるようになっていればOKです。

npx esbuild index.ts --bundle --minify --sourcemap --platform=node --target=es2020 --outfile=dist/index.js

このコマンドを実行するとビルドの成果物がdist/index.jsに出力されます。このファイルには依存関係がすべてバンドル(1つのファイルに固められる)されていて、「基本的には」単体で動作します。

アプリケーションにPrismaを組み込む

続いてPrismaの公式ドキュメントに沿ってアプリケーションからDBにアクセスするコードを追加します。開発環境でDBに接続マイグレーションができることを確認します。

AWSインフラの構築

AWS上にRDS、VPC、Lambda、セキュリティグループなど必要なリソースを作成して、LambdaからRDSに接続できるよう設定します。

さて、説明をかなり端折ってしまい申し訳ないですが、細かく手順を書き始めるといつまで経っても本題にたどり着けないのでご容赦ください。ようやく準備が終わったので、いよいよ本題です。

binaryTargetsの指定

schema.prismaファイルにbinaryTargetsの設定を追加します。以下は「Node.js 20.xかつx86_64」のケースの設定です。Node.jsのバージョンやアーキテクチャの種類に応じて"rhel-openssl-3.0.x"の部分の設定が変わることに要注意です。詳しくはPrismaのドキュメントを参照してください。

generator client {
  provider = "prisma-client-js"
  binaryTargets = ["native", "rhel-openssl-3.0.x"]
}

なお、この設定を入れてprisma generateを実行することによりPrisma Clientフォルダ配下に該当環境向けのQuery Engineファイルが配置されます。後述しますが、このファイルをアーティファクトに含めてやる必要があります。

node_modules/.prisma/client/libquery_engine-rhel-openssl-3.0.x.so.node

アーティファクトの作成

esbuildコマンドでアプリケーションのビルド(index.js)を行いましたが、前述の通りアーティファクトにはこの他にPrisma Query Engineファイル(*.so.node)を含める必要があります。最低限必要なファイルは以下の2つです。

  • dist/index.js
  • dist/libquery_engine-rhel-openssl-3.0.x.so.node

これらをzipで固めます。

cd dist
zip -r batch.zip ./*

Lambdaにデプロイ

先の手順で作成したアーティファクトをLambdaにデプロイします。以下のコマンドではbatchというLambda関数を更新しています。

aws lambda update-function-code --function-name batch --zip-file fileb://batch.zip --publish --query Version --output json

環境変数PRISMA_QUERY_ENGINE_LIBRARYの指定

この状態でLambda関数を動かすとQuery Engineが見つからない旨エラーが出るはずです。そこで、Lambda関数の環境変数に以下を追加します。

PRISMA_QUERY_ENGINE_LIBRARY "./libquery_engine-linux-arm64-openssl-3.0.x.so.node"

PRISMA_QUERY_ENGINE_LIBRARYQuery Engineの場所を指定するための環境変数です。つまり、index.jsと同じパス上にあるQuery Engineファイルを参照するよう指定する設定です。当然ながら、Node.jsのバージョンやアーキテクチャが変わることによりQuery Engineのファイルが変更になる場合、そのファイルを参照するよう環境変数も調整する必要があります。

参考情報

まとめ

おとなしくAWS SAMやServerless Frameworkを使えって話かもしれませんが、満たすべき条件を知っていれば、ツールが変わっても応用ができるようになります。以上です。

Discussion