使用容器映像部署 Node.js Lambda 函数
有三种方法可以为 Node.js Lambda 函数构建容器映像:
-
AWS 基本映像会预加载一个语言运行时系统、一个用于管理 Lambda 和函数代码之间交互的运行时系统接口客户端,以及一个用于本地测试的运行时系统接口仿真器。
-
AWS 仅限操作系统的运行时系统
包含 Amazon Linux 发行版和运行时系统接口模拟器 。这些镜像通常用于为编译语言(例如 Go 和 Rust)以及 Lambda 未提供基础映像的语言或语言版本(例如 Node.js 19)创建容器镜像。您也可以使用仅限操作系统的基础映像来实施自定义运行时系统。要使映像与 Lambda 兼容,您必须在映像中包含 Node.js 的运行时系统接口客户端。 -
您还可以使用其他容器注册表的备用基本映像,例如 Alpine Linux 或 Debian。您还可以使用您的组织创建的自定义映像。要使映像与 Lambda 兼容,您必须在映像中包含 Node.js 的运行时系统接口客户端。
提示
要缩短 Lambda 容器函数激活所需的时间,请参阅 Docker 文档中的使用多阶段构建
此页面介绍了如何为 Lambda 构建、测试和部署容器映像。
Node.js 的 AWS 基本映像
AWS 为 Node.js 提供了以下基本映像:
标签 | 运行时 | 操作系统 | Dockerfile | 淘汰 |
---|---|---|---|---|
20 |
Node.js 20 | Amazon Linux 2023 | GitHub 上适用于 Node.js 20 的 Dockerfile |
未计划 |
18 |
Node.js 18 | Amazon Linux 2 | GitHub 上适用于 Node.js 18 的 Dockerfile |
2025 年 7 月 31 日 |
Amazon ECR 存储库:gallery.ecr.aws/lambda/nodejs
Node.js 20 及更高版本的基础映像基于 Amazon Linux 2023 最小容器映像。早期的基础映像使用 Amazon Linux 2。与 Amazon Linux 2 相比,AL2023 具有多项优势,包括较小的部署占用空间以及 glibc
等更新版本的库。
基于 AL2023 的映像使用 microdnf
(符号链接为 dnf
)作为软件包管理器,而不是 Amazon Linux 2 中的默认软件包管理器 yum
。microdnf
是 dnf
的独立实现。有关基于 AL2023 的映像中已包含软件包的列表,请参阅 Comparing packages installed on Amazon Linux 2023 Container Images 中的 Minimal Container 列。有关 AL2023 和 Amazon Linux 2 之间区别的更多信息,请参阅 AWS 计算博客上的 Introducing the Amazon Linux 2023 runtime for AWS Lambda
注意
要在本地运行基于 AL2023 的映像,包括使用 AWS Serverless Application Model(AWS SAM),您必须使用 Docker 版本 20.10.10 或更高版本。
使用 Node.js 的 AWS 基本映像
要完成本节中的步骤,您必须满足以下条件:
-
Docker
(Node.js 20 及更高版本基础映像的最低版本为 20.10.10) -
Node.js
从 Node.js 的 AWS 的基本映像创建容器映像
-
为项目创建一个目录,然后切换到该目录。
mkdir example cd example
-
使用
npm
创建新的 Node.js 项目。要在交互式体验中接受提供的默认选项,请按Enter
。npm init
-
创建名为
index.js
的新文件。您可以将以下示例函数代码添加到文件中进行测试,也可以使用您自己的函数代码。例 CommonJS 处理程序
exports.handler = async (event) => { const response = { statusCode: 200, body: JSON.stringify('Hello from Lambda!'), }; return response; };
-
如果函数依赖于 AWS SDK for JavaScript 之外的库,请使用 npm
将其添加到程序包。 -
使用以下配置创建一个新的 Dockerfile。
-
将
FROM
属性设置为基本映像的 URI。 -
使用 COPY 命令将函数代码和运行时系统依赖项复制到
{LAMBDA_TASK_ROOT}
,此为 Lambda 定义的环境变量。 -
将
CMD
参数设置为 Lambda 函数处理程序。
请注意,示例 Dockerfile 不包含 USER 指令
。当您将容器映像部署到 Lambda 时,Lambda 会自动定义具有最低权限的默认 Linux 用户。这与标准 Docker 行为不同,标准 Docker 在未提供 USER
指令时默认为root
用户。例 Dockerfile
FROM
public.ecr.aws/lambda/nodejs:20
# Copy function code COPYindex.js
${LAMBDA_TASK_ROOT} # Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile) CMD [ "index.handler
" ] -
-
使用 docker build
命令构建 Docker 映像。以下示例将映像命名为 docker-image
并为其提供test
标签。 docker build --platform linux/amd64 -t
docker-image
:test
.注意
该命令指定了
--platform linux/amd64
选项,可确保无论生成计算机的架构如何,容器始终与 Lambda 执行环境兼容。如果打算使用 ARM64 指令集架构创建 Lambda 函数,请务必将命令更改为使用--platform linux/arm64
选项。
-
使用 docker run 命令启动 Docker 映像。在此示例中,
docker-image
是映像名称,test
是标签。docker run --platform linux/amd64 -p 9000:8080
docker-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 kill
3766c4ab331c
将映像上传到 Amazon ECR 并创建 Lambda 函数
-
运行 get-login-password
命令,以针对 Amazon ECR 注册表进行 Docker CLI 身份验证。 -
将
--region
值设置为要在其中创建 Amazon ECR 存储库的 AWS 区域。 -
将
111122223333
替换为您的 AWS 账户 ID。
aws ecr get-login-password --region
us-east-1
| docker login --username AWS --password-stdin111122223333
.dkr.ecr.us-east-1
.amazonaws.com -
-
使用 create-repository
命令在 Amazon ECR 中创建存储库。 aws ecr create-repository --repository-name
hello-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 tag
docker-image
:test
111122223333
.dkr.ecr.us-east-1
.amazonaws.com/hello-world
:latest -
-
运行 docker push
命令,以将本地映像部署到 Amazon ECR 存储库。确保存储库 URI 末尾包含 :latest
。docker push
111122223333
.dkr.ecr.us-east-1
.amazonaws.com/hello-world
:latest -
如果您还没有函数的执行角色,请创建执行角色。在下一步中,您需要提供角色的 Amazon 资源名称(ARN)。
-
创建 Lambda 函数。对于
ImageUri
,指定之前的存储库 URI。确保 URI 末尾包含:latest
。aws lambda create-function \ --function-name
hello-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-name
hello-world
response.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-name
hello-world
\ --image-uri111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
\ --publish
将备用基本映像与运行时系统接口客户端配合使用
如果使用仅限操作系统的基础映像或者备用基础映像,则必须在映像中包括运行时系统接口客户端。运行时系统接口客户端可扩展 将 Lambda 运行时 API 用于自定义运行时,用于管理 Lambda 和函数代码之间的交互。
使用 npm 包管理器安装 Node.js 运行时系统接口客户端
npm install aws-lambda-ric
您也可以从 GitHub 下载 Node.js 运行时接口客户端
14.x
16.x
18.x
20.x
以下示例演示了如何使用非 AWS 基本映像为 Node.js 构建容器映像。示例 Dockerfile 使用 buster
基本映像。Docker 包含运行时系统接口客户端。
要完成本节中的步骤,您必须满足以下条件:
-
Node.js
要从非 AWS 基本映像创建容器映像
-
为项目创建一个目录,然后切换到该目录。
mkdir example cd example
-
使用
npm
创建新的 Node.js 项目。要在交互式体验中接受提供的默认选项,请按Enter
。npm init
-
创建名为
index.js
的新文件。您可以将以下示例函数代码添加到文件中进行测试,也可以使用您自己的函数代码。例 CommonJS 处理程序
exports.handler = async (event) => { const response = { statusCode: 200, body: JSON.stringify('Hello from Lambda!'), }; return response; };
-
创建新 Dockerfile。以下 Dockerfile 使用
buster
基本映像而不是 AWS 基本映像。Dockerfile 包含运行时系统接口客户端,该客户端可使映像与 Lambda 兼容。Dockerfile 使用多阶段构建 。第一阶段将创建一个构建映像,作为安装函数依赖项的标准 Node.js 环境。第二阶段创建一个更精简的映像,其中包含函数代码及其依赖项。此机制可缩减最终映像大小。 -
将
FROM
属性设置为基本映像标识符。 -
使用
COPY
命令将复制函数代码和运行时系统依赖项。 -
将
ENTRYPOINT
设置为您希望 Docker 容器在启动时运行的模块。在本例中,模块为运行时系统接口客户端。 -
将
CMD
参数设置为 Lambda 函数处理程序。
请注意,示例 Dockerfile 不包含 USER 指令
。当您将容器映像部署到 Lambda 时,Lambda 会自动定义具有最低权限的默认 Linux 用户。这与标准 Docker 行为不同,标准 Docker 在未提供 USER
指令时默认为root
用户。例 Dockerfile
# Define custom function directory ARG FUNCTION_DIR="/function" FROM
node:20-buster
as build-image # Include global arg in this stage of the build ARG FUNCTION_DIR # Install build dependencies RUN apt-get update && \ apt-get install -y \ g++ \ make \ cmake \ unzip \ libcurl4-openssl-dev # Copy function code RUN mkdir -p ${FUNCTION_DIR} COPY . ${FUNCTION_DIR} WORKDIR ${FUNCTION_DIR} # Install Node.js dependencies RUN npm install # Install the runtime interface client RUN npm install aws-lambda-ric # Grab a fresh slim copy of the image to reduce the final size FROMnode:20-buster-slim
# Required for Node runtimes which use npm@8.6.0+ because # by default npm writes logs under /home/.npm and Lambda fs is read-only ENV NPM_CONFIG_CACHE=/tmp/.npm # Include global arg in this stage of the build ARG FUNCTION_DIR # Set working directory to function root directory WORKDIR ${FUNCTION_DIR} # Copy in the built dependencies COPY --from=build-image ${FUNCTION_DIR} ${FUNCTION_DIR} # Set runtime interface client as default command for the container runtime ENTRYPOINT ["/usr/local/bin/npx", "aws-lambda-ric"
] # Pass the name of the function handler as an argument to the runtime CMD ["index.handler
"] -
-
使用 docker build
命令构建 Docker 映像。以下示例将映像命名为 docker-image
并为其提供test
标签。 docker build --platform linux/amd64 -t
docker-image
:test
.注意
该命令指定了
--platform linux/amd64
选项,可确保无论生成计算机的架构如何,容器始终与 Lambda 执行环境兼容。如果打算使用 ARM64 指令集架构创建 Lambda 函数,请务必将命令更改为使用--platform linux/arm64
选项。
使用运行时系统接口仿真器
在本地计算机上安装并运行运行时系统接口仿真器
-
从项目目录中,运行以下命令以从 GitHub 下载运行时系统接口仿真器(x86-64 架构)并将其安装在本地计算机上。
-
使用 docker run 命令启动 Docker 映像。请注意以下几点:
-
docker-image
是映像名称,test
是标签。 -
/usr/local/bin/npx aws-lambda-ric index.handler
是ENTRYPOINT
,后跟您 Dockerfile 中的CMD
。
此命令会将映像作为容器运行,并在
localhost:9000/2015-03-31/functions/function/invocations
创建本地端点。注意
如果为 ARM64 指令集架构创建 Docker 映像,请务必使用
--platform linux/
选项,而不是arm64
--platform linux/
选项。amd64
-
-
将事件发布到本地端点。
-
获取容器 ID。
docker ps
-
使用 docker kill
命令停止容器。在此命令中,将 3766c4ab331c
替换为上一步中的容器 ID。docker kill
3766c4ab331c
将映像上传到 Amazon ECR 并创建 Lambda 函数
-
运行 get-login-password
命令,以针对 Amazon ECR 注册表进行 Docker CLI 身份验证。 -
将
--region
值设置为要在其中创建 Amazon ECR 存储库的 AWS 区域。 -
将
111122223333
替换为您的 AWS 账户 ID。
aws ecr get-login-password --region
us-east-1
| docker login --username AWS --password-stdin111122223333
.dkr.ecr.us-east-1
.amazonaws.com -
-
使用 create-repository
命令在 Amazon ECR 中创建存储库。 aws ecr create-repository --repository-name
hello-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 tag
docker-image
:test
111122223333
.dkr.ecr.us-east-1
.amazonaws.com/hello-world
:latest -
-
运行 docker push
命令,以将本地映像部署到 Amazon ECR 存储库。确保存储库 URI 末尾包含 :latest
。docker push
111122223333
.dkr.ecr.us-east-1
.amazonaws.com/hello-world
:latest -
如果您还没有函数的执行角色,请创建执行角色。在下一步中,您需要提供角色的 Amazon 资源名称(ARN)。
-
创建 Lambda 函数。对于
ImageUri
,指定之前的存储库 URI。确保 URI 末尾包含:latest
。aws lambda create-function \ --function-name
hello-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-name
hello-world
response.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-name
hello-world
\ --image-uri111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
\ --publish