AWS Lambdaへのデプロイ
このガイドでは、Prisma ORMを使用するプロジェクトをAWS Lambdaにデプロイする際の一般的な問題を回避する方法を説明します。
AWS Lambdaへのデプロイにデプロイフレームワークは必須ではありませんが、このガイドでは以下のフレームワークでのデプロイについて説明します。
- AWS Serverless Application Model (SAM)は、サーバーレスアプリケーションの作成に使用できるAWSのオープンソースフレームワークです。AWS SAMにはAWS SAM CLIが含まれており、これを使用してアプリケーションをビルド、テスト、デプロイできます。
- Serverless Frameworkは、ワークフローの自動化とAWSリソースのプロビジョニングを支援するCLIを提供します。Prisma ORMはServerless Frameworkと「そのまま」うまく機能しますが、スムーズなデプロイとパフォーマンスを確保するためにプロジェクト内でいくつかの改善を行うことができます。また、
serverless-webpack
またはserverless-bundle
ライブラリを使用している場合は、追加の設定が必要です。 - SSTは、開発者がアプリケーションを定義、テスト、デバッグ、デプロイすることを容易にするツールを提供します。Prisma ORMはSSTとよく連携しますが、スキーマがSSTによって正しくパッケージ化されるように設定する必要があります。
AWS Lambdaへのデプロイに関する一般的な考慮事項
このセクションでは、フレームワークに関係なくアプリケーションに行う必要がある変更について説明します。これらの手順に従った後、使用しているフレームワークの手順に従ってください。
Prismaスキーマでバイナリターゲットを定義する
Node.jsのバージョンに応じて、Prismaスキーマのgenerator
ブロックにrhel-openssl-1.0.x
またはrhel-openssl-3.0.x
を含める必要があります
- Node.js 16および18
- Node.js 20以降
binaryTargets = ["native", "rhel-openssl-1.0.x"]
binaryTargets = ["native", "rhel-openssl-3.0.x"]
これは、開発環境とデプロイ環境で使用されるランタイムが異なるため必要です。binaryTarget
を追加して、互換性のあるPrisma ORMエンジンファイルを利用可能にしてください。
arm64アーキテクチャのLambda関数
arm64アーキテクチャ (AWS Graviton2プロセッサ)を使用するLambda関数は、arm64
プリコンパイル済みエンジンファイルを使用する必要があります。
schema.prisma
ファイルのgenerator
ブロックに以下を追加します。
binaryTargets = ["native", "linux-arm64-openssl-1.0.x"]
Prisma CLIバイナリターゲット
AWS Lambda内でマイグレーションを実行することは推奨されませんが、一部のアプリケーションでは必要になります。これらのケースでは、PRISMA_CLI_BINARY_TARGETS環境変数を使用して、prisma migrate
を含むPrisma CLIコマンドが正しいスキーマエンジンにアクセスできるようにすることができます。
AWS Lambdaの場合、以下の環境変数を追加する必要があります。
PRISMA_CLI_BINARY_TARGETS=native,rhel-openssl-1.0.x
prisma migrate
はprisma
パッケージ内のコマンドです。通常、このパッケージは開発依存関係としてインストールされます。セットアップによっては、Lambdaにアップロードされて実行されるバンドルまたはアーカイブに含めるために、このパッケージを代わりに依存関係としてインストールする必要がある場合があります。
コネクションプーリング
Function as a Service (FaaS) 環境では、各関数呼び出しは通常、新しいデータベース接続を作成します。継続的に実行されるNode.jsサーバーとは異なり、これらの接続は実行間で維持されません。サーバーレス環境でのパフォーマンスを向上させるには、各関数呼び出しごとに新しい接続を作成するのではなく、既存のデータベース接続を再利用するためにコネクションプーリングを実装します。
この問題を解決するために、コネクションプーリングにはAccelerateを使用するか、組み込みのコネクションプーリングを持つPrisma Postgresを使用できます。その他の解決策については、サーバーレス環境向けコネクション管理ガイドを参照してください。
AWS SAMによるデプロイ
環境変数の読み込み
AWS SAMは、.env
ファイルからの値の読み込みを直接サポートしていません。これらのパラメータを保存および取得するには、AWSのサービスを使用する必要があります。このガイドでは、オプションと、パラメータ、SSM、Secrets Managerなどに値を保存および取得する方法について詳しく説明しています。
必要なファイルの読み込み
AWS SAMはTypeScriptコードをバンドルするためにesbuildを使用します。しかし、esbuildの全APIは公開されておらず、esbuildプラグインはサポートされていません。これにより、特定のファイル(schema.prisma
など)が実行時に利用可能である必要があるため、アプリケーションでPrisma ORMを使用する際に問題が発生します。
これを回避するには、必要なファイルをコード内で直接参照して、正しくバンドルされるようにする必要があります。アプリケーションでは、Prisma ORMがインスタンス化される場所に以下の行を追加できます。
import schema from './prisma/schema.prisma'
import x from './node_modules/.prisma/client/libquery_engine-rhel-openssl-1.0.x.so.node'
if (process.env.NODE_ENV !== 'production') {
console.debug(schema, x)
}
Serverless Frameworkによるデプロイ
.env
ファイルを介した環境変数の読み込み
関数がデータベースにアクセスするには、DATABASE_URL
環境変数が必要です。serverless-dotenv-plugin
を使用すると、デプロイで.env
ファイルを使用できるようになります。
まず、プラグインがインストールされていることを確認してください
npm install -D serverless-dotenv-plugin
次に、serverless.yml
のプラグインリストにserverless-dotenv-plugin
を追加します
plugins:
- serverless-dotenv-plugin
これで、.env
ファイル内の環境変数がパッケージまたはデプロイ時に自動的にロードされます。
serverless package
必要なファイルのみをデプロイする
デプロイのフットプリントを減らすために、アプリケーションが必要とするファイルのみをアップロードするようにデプロイプロセスを更新できます。以下のServerless設定ファイルserverless.yml
は、Lambdaランタイムに関連するPrisma ORMエンジンファイルのみを含み、それ以外を除外するpackage
パターンを示しています。これにより、Serverless Frameworkがアップロードのためにアプリをパッケージ化する際に、1つのエンジンファイルのみが含まれるようになります。これにより、パッケージ化されたアーカイブが可能な限り小さくなります。
package:
patterns:
- '!node_modules/.prisma/client/libquery_engine-*'
- 'node_modules/.prisma/client/libquery_engine-rhel-*'
- '!node_modules/prisma/libquery_engine-*'
- '!node_modules/@prisma/engines/**'
- '!node_modules/.cache/prisma/**' # only required for Windows
ARM64アーキテクチャのLambda関数にデプロイする場合、Serverless設定ファイルを以下のように更新してarm64
エンジンファイルをパッケージ化する必要があります。
package:
patterns:
- '!node_modules/.prisma/client/libquery_engine-*'
- 'node_modules/.prisma/client/libquery_engine-linux-arm64-*'
- '!node_modules/prisma/libquery_engine-*'
- '!node_modules/@prisma/engines/**'
serverless-webpack
を使用する場合は、以下のserverless webpackによるデプロイを参照してください。
serverless-webpack
によるデプロイ
serverless-webpack
を使用する場合、schema.prisma
が適切にバンドルされるように追加の設定が必要です。以下の操作が必要です。
copy-webpack-plugin
でschema.prisma
をコピーします。serverless.yml
のcustom > webpack > packagerOptions > scripts
を通じてprisma generate
を実行します。- 正しいPrisma ORMエンジンファイルのみをパッケージ化することで、40MB以上の容量を節約できます。
1. webpack固有の依存関係をインストールする
まず、以下のwebpack依存関係がインストールされていることを確認してください
npm install --save-dev webpack webpack-node-externals copy-webpack-plugin serverless-webpack
2. webpack.config.js
を更新する
webpack.config.js
で、以下のようにexternals
をnodeExternals()
に設定してください
const nodeExternals = require('webpack-node-externals')
module.exports = {
// ... other configuration
externals: [nodeExternals()],
// ... other configuration
}
webpack.config.js
ファイルのplugins
プロパティを更新して、copy-webpack-plugin
を含めます
const nodeExternals = require('webpack-node-externals')
const CopyPlugin = require('copy-webpack-plugin')
module.exports = {
// ... other configuration
externals: [nodeExternals()],
plugins: [
new CopyPlugin({
patterns: [
{ from: './node_modules/.prisma/client/schema.prisma', to: './' }, // you may need to change `to` here.
],
}),
],
// ... other configuration
}
このプラグインを使用すると、schema.prisma
ファイルをバンドルされたコードにコピーできます。Prisma ORMは、クエリがスキーマに従ってエンコードおよびデコードされることを保証するために、schema.prisma
が存在することを必要とします。ほとんどの場合、バンドラーはこのファイルをデフォルトで含まないため、アプリケーションは実行に失敗します。
アプリケーションのバンドル方法によっては、スキーマを./
以外の場所にコピーする必要がある場合があります。serverless package
コマンドを使用してコードをローカルでパッケージ化し、スキーマをどこに配置すべきか確認してください。
追加の設定については、Serverless Webpackのドキュメントを参照してください。
3. serverless.yml
を更新する
serverless.yml
ファイルで、custom > webpack
ブロックにpackagerOptions > scripts
の下に以下のようにprisma generate
があることを確認してください。
custom:
webpack:
packagerOptions:
scripts:
- prisma generate
これにより、webpackがコードをバンドルした後、Prisma Clientがスキーマに従って生成されることが保証されます。この手順がないと、アプリは実行に失敗します。
最後に、AWS Lambdaランタイムと一致しないPrisma ORMクエリエンジンを除外します。serverless.yml
を以下のスクリプトを追加して更新し、必要なクエリエンジンであるrhel-openssl-1.0.x
のみが最終パッケージアーカイブに含まれるようにします。
custom:
webpack:
packagerOptions:
scripts:
- prisma generate
-- find . -name "libquery_engine-*" -not -name "libquery_engine-rhel-openssl-*" | xargs rm
ARM64アーキテクチャのLambda関数にデプロイする場合、find
コマンドを以下のように更新する必要があります。
custom:
webpack:
packagerOptions:
scripts:
- prisma generate
-- find . -name "libquery_engine-*" -not -name "libquery_engine-arm64-openssl-*" | xargs rm
4. まとめ
これで、アプリケーションを再パッケージ化して再デプロイできます。これを行うには、serverless deploy
を実行します。Webpackの出力には、copy-webpack-plugin
によってスキーマが移動されたことが表示されます。
serverless package
SSTによるデプロイ
環境変数の操作
SSTは.env
ファイルをサポートしていますが、推奨されません。SSTは、これらの環境変数に安全な方法でアクセスするためにConfig
を使用することを推奨しています。
Config
の入門には、こちらのSSTガイドがステップバイステップで説明しています。DATABASE_URL
という新しいシークレットを作成し、そのシークレットをアプリにバインドしていると仮定すると、以下のようにPrismaClient
を設定できます。
import { PrismaClient } from '@prisma/client'
import { Config } from 'sst/node/config'
const globalForPrisma = global as unknown as { prisma: PrismaClient }
export const prisma =
globalForPrisma.prisma ||
new PrismaClient({
datasourceUrl: Config.DATABASE_URL,
})
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
export default prisma