メインコンテンツにスキップ

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 のいずれかを含める必要があります。

binaryTargets = ["native", "rhel-openssl-1.0.x"]

これは、開発とデプロイで使用されるランタイムが異なるため必要です。互換性のある Prisma ORM エンジンファイルを利用できるようにするために、binaryTarget を追加してください。

arm64 アーキテクチャの Lambda 関数

arm64 アーキテクチャ(AWS Graviton2 プロセッサ)を使用する Lambda 関数は、arm64 アーキテクチャ (AWS Graviton2 プロセッサ)

schema.prisma ファイルの generator ブロックに、以下を追加します。

schema.prisma
binaryTargets = ["native", "linux-arm64-openssl-1.0.x"]

Prisma CLI バイナリターゲット

AWS Lambda 内でマイグレーションを実行することはお勧めしませんが、一部のアプリケーションではそれが必要になります。このような場合は、PRISMA_CLI_BINARY_TARGETS 環境変数を使用して、prisma migrate を含む Prisma CLI コマンドが正しいスキーマエンジンにアクセスできるようにしてください。

AWS Lambda の場合、次の環境変数を追加する必要があります。

.env
PRISMA_CLI_BINARY_TARGETS=native,rhel-openssl-1.0.x
情報

prisma migrateprisma パッケージのコマンドです。通常、このパッケージは開発依存関係としてインストールされます。セットアップによっては、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 がインスタンス化されるアプリケーションに次の行を追加できます。

app.ts
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 を追加します。

serverless.yml
plugins:
- serverless-dotenv-plugin

`.env` ファイルの環境変数が、パッケージまたはデプロイ時に自動的にロードされるようになります。

serverless package
表示CLI結果

必要なファイルのみをデプロイする

デプロイメントのフットプリントを削減するために、アプリケーションに必要なファイルのみをアップロードするようにデプロイプロセスを更新できます。以下の Serverless 構成ファイル serverless.yml は、Lambda ランタイムに関連する Prisma ORM エンジンファイルのみを含み、他を除外する package パターンを示しています。これは、Serverless Framework がアップロード用にアプリをパッケージ化するときに、1 つのエンジンファイルのみが含まれることを意味します。これにより、パッケージ化されたアーカイブが可能な限り小さくなります。

serverless.yml
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 構成ファイルを更新する必要があります。

serverless.yml
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 が適切にバンドルされるように追加の構成が必要です。次のことを行う必要があります。

  1. copy-webpack-plugin を使用して schema.prisma をコピーします。copy-webpack-plugin
  2. serverless.ymlcustom > webpack > packagerOptions > scripts 経由で prisma generate を実行します。
  3. 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() に設定していることを確認してください。

webpack.config.js
const nodeExternals = require('webpack-node-externals')

module.exports = {
// ... other configuration
externals: [nodeExternals()],
// ... other configuration
}

webpack.config.js ファイルの plugins プロパティを更新して、copy-webpack-plugin を含めます。

webpack.config.js
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 > scriptsprisma generate が次のように設定されていることを確認してください。

serverless.yml
custom:
webpack:
packagerOptions:
scripts:
- prisma generate

これにより、webpack がコードをバンドルした後、Prisma Client がスキーマに従って生成されるようになります。この手順がないと、アプリは実行に失敗します。

最後に、AWS Lambda ランタイムに一致しない Prisma ORM クエリエンジン を除外する必要があります。必要なクエリエンジン rhel-openssl-1.0.x のみが最終的なパッケージ化されたアーカイブに含まれるようにする次のスクリプトを追加して、serverless.yml を更新します。

serverless.yml
custom:
webpack:
packagerOptions:
scripts:
- prisma generate
-- find . -name "libquery_engine-*" -not -name "libquery_engine-rhel-openssl-*" | xargs rm

ARM64 アーキテクチャの Lambda 関数にデプロイする場合は、find コマンドを次のように更新する必要があります。

serverless.yml
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
表示CLI結果

SST を使用したデプロイ

環境変数の操作

SST は `.env` ファイルをサポートしていますが、推奨されていません。SST は、これらの環境変数に安全な方法でアクセスするために Config を使用することを推奨しています。

ここで入手できる SST ガイド は、Config を始めるためのステップバイステップガイドです。DATABASE_URL という名前の新しいシークレットを作成し、そのシークレットをアプリにバインドした と仮定すると、次のように PrismaClient を設定できます。

prisma.ts
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