使用容器镜像在 Lambda 中部署转换后的 TypeScript 代码
您可以将 TypeScript 代码作为 Node.js 容器镜像部署到 AWS Lambda 函数中。AWS 将为 Node.js 提供基本镜像,以帮助您构建容器镜像。这些基本映像会预加载一个语言运行时和在 Lambda 上运行映像所需的其他组件。AWS 为每个基本映像提供 Dockerfile,以帮助构建容器映像。
如果使用社群或私有企业基本镜像,则必须将 Node.js 运行时接口客户端 (RIC) 添加到该基本镜像,以使其与 Lambda 兼容。
Lambda 提供了可用于本地测试的运行时系统接口仿真器。Node.js 的 AWS 基本映像包含运行时系统接口仿真器。如果您使用备用基本映像,例如 Alpine Linux 或 Debian 映像,则可将仿真器构建到映像中
使用 Node.js 基本映像构建和打包 TypeScript 函数代码
要完成本节中的步骤,您必须满足以下条件:
通过AWS基本映像为 Lambda 创建映像
-
在本地计算机上,为新函数创建项目目录。
-
使用
npm或您选择的软件包管理器创建一个新的 Node.js 项目。npm init -
添加 @types/aws-lambda
和 esbuild 软件包作为开发依赖项。 @types/aws-lambda程序包包含 Lambda 的类型定义。npm install -D @types/aws-lambda esbuild -
将构建脚本
添加到 package.json文件。"scripts": { "build": "esbuild index.ts --bundle --minify --sourcemap --platform=node --target=es2020 --outfile=dist/index.js" } -
创建名为
index.ts的新文件。将以下示例代码添加到该新文件。这是适用于 Lambda 函数的代码。该函数将返回一条hello world消息。注意
import语句从 @types/aws-lambda中导入类型定义。它不导入 aws-lambdaNPM 程序包,这是一个无关的第三方工具。有关更多信息,请参阅 DefinitelyTyped GitHub 存储库中的 aws-lambda。 import { Context, APIGatewayProxyResult, APIGatewayEvent } from 'aws-lambda'; export const handler = async (event: APIGatewayEvent, context: Context): Promise<APIGatewayProxyResult> => { console.log(`Event: ${JSON.stringify(event, null, 2)}`); console.log(`Context: ${JSON.stringify(context, null, 2)}`); return { statusCode: 200, body: JSON.stringify({ message: 'hello world', }), }; }; -
使用以下配置创建一个新的 Dockerfile。
-
将
FROM属性设置为基本映像的 URI。 -
设置
CMD参数以指定 Lambda 函数处理程序。
以下示例 Dockerfile 将使用多阶段构建。第一步将 TypeScript 代码转换为 JavaScript。第二步生成仅包含 JavaScript 文件和生产依赖项的容器映像。
请注意,示例 Dockerfile 不包含 USER 指令
。当您将容器映像部署到 Lambda 时,Lambda 会自动定义具有最低权限的默认 Linux 用户。这与标准 Docker 行为不同,标准 Docker 在未提供 USER指令时默认为root用户。例 Dockerfile
FROM public.ecr.aws/lambda/nodejs:22 as builder WORKDIR /usr/app COPY package.json index.ts ./ RUN npm install RUN npm run build FROM public.ecr.aws/lambda/nodejs:22 WORKDIR ${LAMBDA_TASK_ROOT} COPY --from=builder /usr/app/dist/* ./ CMD ["index.handler"] -
-
使用 docker build
命令构建 Docker 映像。以下示例将映像命名为 docker-image并为其提供test标签。要使您的映像与 Lambda 兼容,您必须使用 --provenance=false选项。docker buildx build --platform linux/amd64 --provenance=false -tdocker-image:test.注意
该命令指定了
--platform linux/amd64选项,可确保无论生成计算机的架构如何,容器始终与 Lambda 执行环境兼容。如果打算使用 ARM64 指令集架构创建 Lambda 函数,请务必将命令更改为使用--platform linux/arm64选项。
-
使用 docker run 命令启动 Docker 映像。在此示例中,
docker-image是映像名称,test是标签。docker run --platform linux/amd64 -p 9000:8080docker-image:test此命令会将映像作为容器运行,并在
localhost:9000/2015-03-31/functions/function/invocations创建本地端点。注意
如果为 ARM64 指令集架构创建 Docker 映像,请务必使用
--platform linux/选项,而不是arm64--platform linux/选项。amd64 -
在新的终端窗口中,将事件发布到本地端点。
-
获取容器 ID。
docker ps -
使用 docker kill
命令停止容器。在此命令中,将 3766c4ab331c替换为上一步中的容器 ID。docker kill3766c4ab331c
将映像上传到 Amazon ECR 并创建 Lambda 函数
-
运行 get-login-password
命令,以针对 Amazon ECR 注册表进行 Docker CLI 身份验证。 -
将
--region值设置为要在其中创建 Amazon ECR 存储库的 AWS 区域。 -
将
111122223333替换为您的 AWS 账户 ID。
aws ecr get-login-password --regionus-east-1| docker login --username AWS --password-stdin111122223333.dkr.ecr.us-east-1.amazonaws.com -
-
使用 create-repository
命令在 Amazon ECR 中创建存储库。 aws ecr create-repository --repository-namehello-world--regionus-east-1--image-scanning-configuration scanOnPush=true --image-tag-mutability MUTABLE注意
Amazon ECR 存储库必须与 Lambda 函数位于同一 AWS 区域 内。
如果成功,您将会看到如下响应:
{ "repository": { "repositoryArn": "arn:aws:ecr:us-east-1:111122223333:repository/hello-world", "registryId": "111122223333", "repositoryName": "hello-world", "repositoryUri": "111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world", "createdAt": "2023-03-09T10:39:01+00:00", "imageTagMutability": "MUTABLE", "imageScanningConfiguration": { "scanOnPush": true }, "encryptionConfiguration": { "encryptionType": "AES256" } } } -
从上一步的输出中复制
repositoryUri。 -
运行 docker tag
命令,将本地映像作为最新版本标记到 Amazon ECR 存储库中。在此命令中: -
docker-image:test是 Docker 映像的名称和标签。这是您在 docker build命令中指定的映像名称和标签。 -
将
<ECRrepositoryUri>替换为复制的repositoryUri。确保 URI 末尾包含:latest。
docker tag docker-image:test<ECRrepositoryUri>:latest示例:
docker tagdocker-image:test111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest -
-
运行 docker push
命令,以将本地映像部署到 Amazon ECR 存储库。确保存储库 URI 末尾包含 :latest。docker push111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest -
如果您还没有函数的执行角色,请创建执行角色。在下一步中,您需要提供角色的 Amazon 资源名称(ARN)。
-
创建 Lambda 函数。对于
ImageUri,指定之前的存储库 URI。确保 URI 末尾包含:latest。aws lambda create-function \ --function-namehello-world\ --package-type Image \ --code ImageUri=111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest \ --rolearn:aws:iam::111122223333:role/lambda-ex注意
只要映像与 Lambda 函数位于同一区域内,您就可以使用其他 AWS 账户中的映像创建函数。有关更多信息,请参阅 Amazon ECR 跨账户权限。
-
调用函数。
aws lambda invoke --function-namehello-worldresponse.json应出现如下响应:
{ "ExecutedVersion": "$LATEST", "StatusCode": 200 } -
要查看函数的输出,请检查
response.json文件。
要更新函数代码,您必须再次构建映像,将新映像上传到 Amazon ECR 存储库,然后使用 update-function-code
Lambda 会将映像标签解析为特定的映像摘要。这意味着,如果您将用于部署函数的映像标签指向 Amazon ECR 中的新映像,则 Lambda 不会自动更新该函数以使用新映像。
要将新映像部署到相同的 Lambda 函数,即使 Amazon ECR 中的映像标签保持不变,也必须使用 update-function-code--publish 选项使用更新的容器映像创建函数的新版本。
aws lambda update-function-code \ --function-namehello-world\ --image-uri111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest\ --publish