部署到 AWS Lambda
本指南介绍了使用 Prisma ORM 将项目部署到 AWS Lambda 时如何避免常见问题。
¥This guide explains how to avoid common issues when deploying a project using Prisma ORM to AWS Lambda.
虽然部署到 AWS Lambda 不需要部署框架,但本指南涵盖了使用以下内容进行部署:
¥While a deployment framework is not required to deploy to AWS Lambda, this guide covers deploying with:
-
AWS 无服务器应用模型 (SAM) 是 AWS 的开源框架,可用于创建无服务器应用。AWS SAM 包括 AWS SAM CLI,你可以使用它来构建、测试和部署应用。
¥AWS Serverless Application Model (SAM) is an open-source framework from AWS that can be used in the creation of serverless applications. AWS SAM includes the AWS SAM CLI, which you can use to build, test, and deploy your application.
-
无服务器框架 提供了一个 CLI,有助于工作流程自动化和 AWS 资源配置。虽然 Prisma ORM 与无服务器框架 "盒子外面" 配合良好,但你的项目中可以进行一些改进,以确保顺利部署和性能。如果你使用
serverless-webpack
或serverless-bundle
库,还需要其他配置。¥Serverless Framework provides a CLI that helps with workflow automation and AWS resource provisioning. While Prisma ORM works well with the Serverless Framework "out of the box", there are a few improvements that can be made within your project to ensure a smooth deployment and performance. There is also additional configuration that is needed if you are using the
serverless-webpack
orserverless-bundle
libraries. -
SST 提供的工具使开发者可以轻松定义、测试、调试和部署其应用。Prisma ORM 与 SST 配合良好,但必须进行配置,以便 SST 正确打包你的架构。
¥SST provides tools that make it easy for developers to define, test, debug, and deploy their applications. Prisma ORM works well with SST but must be configured so that your schema is correctly packaged by SST.
部署到 AWS Lambda 时的一般注意事项
¥General considerations when deploying to AWS Lambda
本节介绍你需要对应用进行的更改,无论框架如何。执行这些步骤后,请执行适合你的框架的步骤。
¥This section covers changes you will need to make to your application, regardless of framework. After following these steps, follow the steps for your framework.
在 Prisma Schema 中定义二进制目标
¥Define binary targets in Prisma Schema
根据 Node.js 的版本,你的 Prisma 架构应在 generator
块中包含 rhel-openssl-1.0.x
或 rhel-openssl-3.0.x
:
¥Depending on the version of Node.js, your Prisma schema should contain either rhel-openssl-1.0.x
or rhel-openssl-3.0.x
in the generator
block:
- Node.js 16 and 18
- Node.js 20+
binaryTargets = ["native", "rhel-openssl-1.0.x"]
binaryTargets = ["native", "rhel-openssl-3.0.x"]
这是必要的,因为开发和部署中使用的运行时不同。添加 binaryTarget
以使兼容的 Prisma ORM 引擎文件可用。
¥This is necessary because the runtimes used in development and deployment differ. Add the binaryTarget
to make the compatible Prisma ORM engine file available.
具有 arm64 架构的 Lambda 函数
¥Lambda functions with arm64 architectures
使用 arm64 架构(AWS Graviton2 处理器) 的 Lambda 函数必须使用 arm64
预编译引擎文件。
¥Lambda functions that use arm64 architectures (AWS Graviton2 processor) must use an arm64
precompiled engine file.
在 schema.prisma
文件的 generator
块中,添加以下内容:
¥In the generator
block of your schema.prisma
file, add the following:
binaryTargets = ["native", "linux-arm64-openssl-1.0.x"]
Prisma CLI 二进制目标
¥Prisma CLI binary targets
虽然我们不建议在 AWS Lambda 中运行迁移,但某些应用将需要它。在这些情况下,你可以使用 PRISMA_CLI_BINARY_TARGETS 环境变量来确保 Prisma CLI 命令(包括 prisma migrate
)能够访问正确的架构引擎。
¥While we do not recommend running migrations within AWS Lambda, some applications will require it. In these cases, you can use the PRISMA_CLI_BINARY_TARGETS environment variable to make sure that Prisma CLI commands, including prisma migrate
, have access to the correct schema engine.
对于 AWS lambda,你必须添加以下环境变量:
¥In the case of AWS lambda, you will have to add the following environment variable:
PRISMA_CLI_BINARY_TARGETS=native,rhel-openssl-1.0.x
prisma migrate
是 prisma
包中的命令。通常,此包作为开发依赖安装。根据你的设置,你可能需要将此包作为依赖安装,以便将其包含在上传到 Lambda 并执行的打包包或存档中。
¥prisma migrate
is a command in the prisma
package. Normally, this package is installed as a dev dependency. Depending on your setup, you may need to install this package as a dependency instead so that it is included in the bundle or archive that is uploaded to Lambda and executed.
连接池
¥Connection pooling
在函数即服务 (FaaS) 环境中,每个函数调用通常都会创建一个新的数据库连接。与连续运行的 Node.js 服务器不同,这些连接不会在执行之间保持。为了在无服务器环境中获得更好的性能,请实现连接池以重用现有的数据库连接,而不是为每个函数调用创建新的连接。
¥In a Function as a Service (FaaS) environment, each function invocation typically creates a new database connection. Unlike a continuously running Node.js server, these connections aren't maintained between executions. For better performance in serverless environments, implement connection pooling to reuse existing database connections rather than creating new ones for each function call.
你可以使用 加速 进行连接池或使用具有内置连接池的 Prisma Postgres 来解决此问题。其他解决方案请参见 无服务器环境的连接管理指南。
¥You can use Accelerate for connection pooling or Prisma Postgres, which has built-in connection pooling, to solve this issue. For other solutions, see the connection management guide for serverless environments.
使用 AWS SAM 进行部署
¥Deploying with AWS SAM
加载环境变量
¥Loading environment variables
AWS SAM 不直接支持从 .env
文件加载值。你必须使用 AWS 的一项服务来存储和检索这些参数。本指南 很好地概述了你的选项以及如何在参数、SSM、Secrets Manager 等中存储和检索值。
¥AWS SAM does not directly support loading values from a .env
file. You will have to use one of AWS's services to store and retrieve these parameters. This guide provides a great overview of your options and how to store and retrieve values in Parameters, SSM, Secrets Manager, and more.
加载所需文件
¥Loading required files
AWS SAM 使用 esbuild 打包你的 TypeScript 代码。但是,完整的 esbuild API 并未公开,并且不支持 esbuild 插件。这会导致在应用中使用 Prisma ORM 时出现问题,因为某些文件(如 schema.prisma
)必须在运行时可用。
¥AWS SAM uses esbuild to bundle your TypeScript code. However, the full esbuild API is not exposed and esbuild plugins are not supported. This leads to problems when using Prisma ORM in your application as certain files (like schema.prisma
) must be available at runtime.
为了解决这个问题,你需要直接在代码中引用所需的文件以正确打包它们。在你的应用中,你可以将以下行添加到实例化 Prisma ORM 的应用中。
¥To get around this, you need to directly reference the needed files in your code to bundle them correctly. In your application, you could add the following lines to your application where Prisma ORM is instantiated.
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)
}
使用无服务器框架进行部署
¥Deploying with the Serverless Framework
通过 .env
文件加载环境变量
¥Loading environment variables via a .env
file
你的函数将需要 DATABASE_URL
环境变量来访问数据库。serverless-dotenv-plugin
将允许你在部署中使用 .env
文件。
¥Your functions will need the DATABASE_URL
environment variable to access the database. The serverless-dotenv-plugin
will allow you to use your .env
file in your deployments.
首先,确保插件已安装:
¥First, make sure that the plugin is installed:
npm install -D serverless-dotenv-plugin
然后,将 serverless-dotenv-plugin
添加到 serverless.yml
中的插件列表中:
¥Then, add serverless-dotenv-plugin
to your list of plugins in serverless.yml
:
plugins:
- serverless-dotenv-plugin
.env
文件中的环境变量现在将自动加载到包或部署中。
¥The environment variables in your .env
file will now be automatically loaded on package or deployment.
serverless package
仅部署所需的文件
¥Deploy only the required files
为了减少部署占用空间,你可以更新部署流程以仅上传应用所需的文件。下面的无服务器配置文件 serverless.yml
显示了 package
模式,其中仅包含与 Lambda 运行时相关的 Prisma ORM 引擎文件,而排除其他文件。这意味着当无服务器框架打包你的应用进行上传时,它仅包含一个引擎文件。这可确保打包的存档尽可能小。
¥To reduce your deployment footprint, you can update your deployment process to only upload the files your application needs. The Serverless configuration file, serverless.yml
, below shows a package
pattern that includes only the Prisma ORM engine file relevant to the Lambda runtime and excludes the others. This means that when Serverless Framework packages your app for upload, it includes only one engine file. This ensures the packaged archive is as small as possible.
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
引擎文件,如下所示:
¥If you are deploying to Lambda functions with ARM64 architecture you should update the Serverless configuration file to package the arm64
engine file, as follows:
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
,请参阅下面的 使用无服务器 webpack 进行部署。
¥If you use serverless-webpack
, see Deployment with serverless webpack below.
使用 serverless-webpack
进行部署
¥Deployment with serverless-webpack
如果你使用 serverless-webpack
,你将需要额外的配置,以便正确打包你的 schema.prisma
。你将需要:
¥If you use serverless-webpack
, you will need additional configuration so that your schema.prisma
is properly bundled. You will need to:
-
用
copy-webpack-plugin
复制你的schema.prisma
。¥Copy your
schema.prisma
withcopy-webpack-plugin
. -
在
serverless.yml
中通过custom > webpack > packagerOptions > scripts
运行prisma generate
。¥Run
prisma generate
viacustom > webpack > packagerOptions > scripts
in yourserverless.yml
. -
仅打包正确的 Prisma ORM 引擎文件即可节省超过 40mb 的容量。
¥Only package the correct Prisma ORM engine file to save more than 40mb of capacity.
1. 安装 webpack 特定依赖
¥ Install webpack specific dependencies
首先,确保安装了以下 webpack 依赖:
¥First, ensure the following webpack dependencies are installed:
npm install --save-dev webpack webpack-node-externals copy-webpack-plugin serverless-webpack
2. 更新 webpack.config.js
¥ Update webpack.config.js
在 webpack.config.js
中,确保将 externals
设置为 nodeExternals()
,如下所示:
¥In your webpack.config.js
, make sure that you set externals
to nodeExternals()
like the following:
const nodeExternals = require('webpack-node-externals')
module.exports = {
// ... other configuration
externals: [nodeExternals()],
// ... other configuration
}
更新 webpack.config.js
文件中的 plugins
属性以包含 copy-webpack-plugin
:
¥Update the plugins
property in your webpack.config.js
file to include the 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
,以确保根据你的架构对查询进行编码和解码。在大多数情况下,打包程序默认不会包含此文件,并且会导致你的应用无法运行。
¥This plugin will allow you to copy your schema.prisma
file into your bundled code. Prisma ORM requires that your schema.prisma
be present in order make sure that queries are encoded and decoded according to your schema. In most cases, bundlers will not include this file by default and will cause your application to fail to run.
根据应用的打包方式,你可能需要将模式复制到 ./
以外的位置。使用 serverless package
命令在本地打包代码,以便你可以查看架构应放置的位置。
¥Depending on how your application is bundled, you may need to copy the schema to a location other than ./
. Use the serverless package
command to package your code locally so you can review where your schema should be put.
有关其他配置,请参阅 无服务器 Webpack 文档。
¥Refer to the Serverless Webpack documentation for additional configuration.
3. 更新 serverless.yml
¥ Update serverless.yml
在 serverless.yml
文件中,确保 custom > webpack
块的 packagerOptions > scripts
下有 prisma generate
,如下所示:
¥In your serverless.yml
file, make sure that the custom > webpack
block has prisma generate
under packagerOptions > scripts
as follows:
custom:
webpack:
packagerOptions:
scripts:
- prisma generate
这将确保在 webpack 打包你的代码后,Prisma 客户端根据你的架构生成。如果没有这一步,你的应用将无法运行。
¥This will ensure that, after webpack bundles your code, the Prisma Client is generated according to your schema. Without this step, your app will fail to run.
最后,你需要排除与 AWS Lambda 运行时不匹配的 Prisma ORM 查询引擎。通过添加以下脚本来更新 serverless.yml
,以确保最终打包存档中仅包含所需的查询引擎 rhel-openssl-1.0.x
。
¥Lastly, you will want to exclude Prisma ORM query engines that do not match the AWS Lambda runtime. Update your serverless.yml
by adding the following script that makes sure only the required query engine, rhel-openssl-1.0.x
, is included in the final packaged archive.
custom:
webpack:
packagerOptions:
scripts:
- prisma generate
-- find . -name "libquery_engine-*" -not -name "libquery_engine-rhel-openssl-*" | xargs rm
如果你要部署到 ARM64 架构的 Lambda 函数,则应将 find
命令更新为以下内容:
¥If you are deploying to Lambda functions with ARM64 architecture you should update the find
command to the following:
custom:
webpack:
packagerOptions:
scripts:
- prisma generate
-- find . -name "libquery_engine-*" -not -name "libquery_engine-arm64-openssl-*" | xargs rm
4. 包起来
¥ Wrapping up
你现在可以重新打包并重新部署你的应用。为此,请运行 serverless deploy
。Webpack 输出将显示使用 copy-webpack-plugin
移动的模式:
¥You can now re-package and re-deploy your application. To do so, run serverless deploy
. Webpack output will show the schema being moved with copy-webpack-plugin
:
serverless package
使用 SST 进行部署
¥Deploying with SST
使用环境变量
¥Working with environment variables
虽然 SST 支持 .env
文件,但 SST 支持 不推荐。SST 建议使用 Config
以安全的方式访问这些环境变量。
¥While SST supports .env
files, it is not recommended. SST recommends using Config
to access these environment variables in a secure way.
SST 指南 可以在这里找到 是开始使用 Config
的分步指南。假设你创建了一个名为 DATABASE_URL
的新密钥并拥有 将该秘密绑定到你的应用,则可以使用以下命令设置 PrismaClient
:
¥The SST guide available here is a step-by-step guide to get started with Config
. Assuming you have created a new secret called DATABASE_URL
and have bound that secret to your app, you can set up PrismaClient
with the following:
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