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"]
これは、開発とデプロイで使用されるランタイムが異なるため必要です。互換性のある Prisma ORM エンジンファイルを利用できるようにするために、binaryTarget
を追加してください。
arm64 アーキテクチャの Lambda 関数
arm64 アーキテクチャ(AWS Graviton2 プロセッサ)を使用する Lambda 関数は、arm64 アーキテクチャ (AWS Graviton2 プロセッサ)
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 のサービスのいずれかを使用する必要があります。このガイド では、オプションの概要と、Parameters、SSM、Secrets Manager などで値を保存および取得する方法について詳しく説明しています。
必要なファイルのロード
AWS SAM は esbuild を使用して TypeScript コードをバンドルします。ただし、esbuild API のすべてが公開されているわけではなく、esbuild プラグインはサポートされていません。これにより、Prisma ORM をアプリケーションで使用する場合、特定ファイル(schema.prisma
など)がランタイムで使用可能である必要があるため、問題が発生します。
これを回避するには、必要なファイルをコード内で直接参照して、正しくバンドルする必要があります。アプリケーションでは、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 関数にデプロイする場合は、次のように arm64
エンジンファイルをパッケージ化するように Serverless 構成ファイルを更新する必要があります。
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
をコピーします。copy-webpack-plugin
。serverless.yml
のcustom > webpack > packagerOptions > scripts
経由でprisma generate
を実行します。- 40MB 以上の容量を節約するために、正しい Prisma ORM エンジンファイルのみをパッケージ化します。
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 クエリエンジン を除外する必要があります。必要なクエリエンジン rhel-openssl-1.0.x
のみが最終的なパッケージ化されたアーカイブに含まれるようにする次のスクリプトを追加して、serverless.yml
を更新します。
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
を使用することを推奨しています。
ここで入手できる SST ガイド は、Config
を始めるためのステップバイステップガイドです。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