使用容器镜像部署 Python Lambda 函数 - AWS Lambda

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用容器镜像部署 Python Lambda 函数

有三种方法可以为 Python Lambda 函数构建容器映像:

提示

要缩短 Lambda 容器函数激活所需的时间,请参阅 Docker 文档中的使用多阶段构建。要构建高效的容器映像,请遵循编写 Dockerfiles 的最佳实践

此页面介绍了如何为 Lambda 构建、测试和部署容器映像。

Python AWS 基本映像

AWS为 Python 提供了以下基本映像:

标签 运行时 操作系统 Dockerfile 淘汰

3.12

Python 3.12 Amazon Linux 2023 适用于 Python 的 Dockerfile 3.12 开启 GitHub

3.11

Python 3.11 Amazon Linux 2 适用于 Python 的 Dockerfile 3.11 开启 GitHub

3.10

Python 3.10 Amazon Linux 2 适用于 Python 的 Dockerfile 3.10 开启 GitHub

3.9

Python 3.9 Amazon Linux 2 适用于 Python 的 Dockerfile 3.9 GitHub

3.8

Python 3.8 Amazon Linux 2 适用于 Python 3.8 的 Dockerfile GitHub

2024 年 10 月 14 日

Amazon ECR 存储库:gallery.ecr.aws/lambda/python

Python 3.12 及更高版本的基础镜像基于亚马逊 Linux 2023 的最小容器镜像。Python 3.8-3.11 基础镜像基于亚马逊 Linux 2 镜像。与 Amazon Linux 2 相比,基于 AL2023 的映像具有多项优势,包括较小的部署占用空间和更新版本的库,例如。glibc

基于 AL2023 的图像使用microdnf(符号链接为dnf)作为包管理器yum,而不是 Amazon Linux 2 中的默认包管理器。 microdnf是的独立实现dnf。有关基于 AL2023 的映像中包含的软件包列表,请参阅比较安装在 Amazon Linux 2023 容器映像上的软件包中的最小容器列。有关 AL2023 和亚马逊 Linux 2 之间区别的更多信息,请参阅 C AWS ompute 博客AWS Lambda上的 Amazon Linux 2023 运行时简介

注意

要在本地运行基于 AL2023 的映像,包括使用 AWS Serverless Application Model (AWS SAM),必须使用 Docker 版本 20.10.10 或更高版本。

基本映像中的依赖项搜索路径

在代码中使用 import 语句时,Python 运行时系统会搜索其搜索路径中的目录,直到找到相应模块或包。默认情况下,运行时系统会首先搜索 {LAMBDA_TASK_ROOT} 目录。如果映像含有包含运行时系统的库的某个版本,则此版本将优先于运行时系统中包含的版本。

搜索路径中的其他步骤取决于您使用的 Python Lambda 基本映像的版本:

  • Python 3.11 及更高版本:包含运行时系统的库和安装了 pip 的库均安装在 /var/lang/lib/python3.11/site-packages 目录中。此目录优先于搜索路径中的 /var/runtime。您可以通过使用 pip 安装更新版本来覆盖 SDK。您可以使用 pip 来验证包含运行时系统的 SDK 及其依赖项是否与您安装的任何程序包兼容。

  • Python 3.8-3.10:包含运行时系统的库安装在 /var/runtime 目录中。安装了 pip 的库安装在 /var/lang/lib/python3.x/site-packages 目录中。此 /var/runtime 目录优先于搜索路径中的 /var/lang/lib/python3.x/site-packages

通过添加以下代码段,您可以查看 Lambda 函数的完整搜索路径。

import sys search_path = sys.path print(search_path)

使用 Python 的 AWS 基本映像

要完成本节中的步骤,您必须满足以下条件:

要从 Python 的 AWS 的基本映像创建容器映像
  1. 为项目创建一个目录,然后切换到该目录。

    mkdir example cd example
  2. 创建名为 lambda_function.py 的新文件。您可以将以下示例函数代码添加到文件中进行测试,也可以使用您自己的函数代码。

    例 Python 函数
    import sys def handler(event, context): return 'Hello from AWS Lambda using Python' + sys.version + '!'
  3. 创建名为 requirements.txt 的新文件。如果您使用的是上一步中的示例函数代码,则可以将文件留空,因为没有依赖项。否则,请列出每个必需的库。例如,如果您的函数使用的是 AWS SDK for Python (Boto3),则 requirements.txt 应如下所示:

    例 requirements.txt
    boto3
  4. 使用以下配置创建一个新的 Dockerfile。

    例 Dockerfile
    FROM public.ecr.aws/lambda/python:3.12 # Copy requirements.txt COPY requirements.txt ${LAMBDA_TASK_ROOT} # Install the specified packages RUN pip install -r requirements.txt # Copy function code COPY lambda_function.py ${LAMBDA_TASK_ROOT} # Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile) CMD [ "lambda_function.handler" ]
  5. 使用 docker build 命令构建 Docker 映像。以下示例将映像命名为 docker-image 并为其提供 test 标签

    docker build --platform linux/amd64 -t docker-image:test .
    注意

    该命令指定了 --platform linux/amd64 选项,可确保无论生成计算机的架构如何,容器始终与 Lambda 执行环境兼容。如果打算使用 ARM64 指令集架构创建 Lambda 函数,请务必将命令更改为使用 --platform linux/arm64 选项。

  1. 使用 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 选项。

  2. 在新的终端窗口中,将事件发布到本地端点。

    Linux/macOS

    在 Linux 和 macOS 中,运行以下 curl 命令:

    curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'

    此命令使用空事件调用函数并返回响应。如果您使用自己的函数代码而不是示例函数代码,则可能需要使用 JSON 负载调用函数。例如:

    curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'
    PowerShell

    在中 PowerShell,运行以下Invoke-WebRequest命令:

    Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{}' -ContentType "application/json"

    此命令使用空事件调用函数并返回响应。如果您使用自己的函数代码而不是示例函数代码,则可能需要使用 JSON 负载调用函数。例如:

    Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{"payload":"hello world!"}' -ContentType "application/json"
  3. 获取容器 ID。

    docker ps
  4. 使用 docker kill 命令停止容器。在此命令中,将 3766c4ab331c 替换为上一步中的容器 ID。

    docker kill 3766c4ab331c
将映像上传到 Amazon ECR 并创建 Lambda 函数
  1. 运行get-login-password命令将 Docker CLI 验证到您的 Amazon ECR 注册表。

    • --region 值设置为要在其中创建 Amazon ECR 存储库的 AWS 区域。

    • 111122223333 替换为您的 AWS 账户 ID。

    aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 111122223333.dkr.ecr.us-east-1.amazonaws.com
  2. 使用 create-repository 命令在 Amazon ECR 中创建存储库。

    aws ecr create-repository --repository-name hello-world --region us-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" } } }
  3. 从上一步的输出中复制 repositoryUri

  4. 运行 docker tag 命令,将本地映像作为最新版本标记到 Amazon ECR 存储库中。在此命令中:

    • docker-image:test 替换为 Docker 映像的名称和标签

    • 将 <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
  5. 运行 docker push 命令,以将本地映像部署到 Amazon ECR 存储库。确保存储库 URI 末尾包含 :latest

    docker push 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
  6. 如果您还没有函数的执行角色,请创建执行角色。在下一步中,您需要提供角色的 Amazon 资源名称(ARN)。

  7. 创建 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 \ --role arn:aws:iam::111122223333:role/lambda-ex
    注意

    只要映像与 Lambda 函数位于同一区域内,您就可以使用其他 AWS 账户中的映像创建函数。有关更多信息,请参阅 Amazon ECR 跨账户权限

  8. 调用函数。

    aws lambda invoke --function-name hello-world response.json

    应出现如下响应:

    { "ExecutedVersion": "$LATEST", "StatusCode": 200 }
  9. 要查看函数的输出,请检查 response.json 文件。

要更新函数代码,您必须重新构建映像,将新映像上传到 Amazon ECR 存储库,然后使用update-function-code命令将映像部署到 Lambda 函数。

将备用基本映像与运行时系统接口客户端配合使用

如果使用仅限操作系统的基础映像或者备用基础映像,则必须在映像中包括运行时系统接口客户端。运行时系统接口客户端可扩展 Lambda 运行时 API,用于管理 Lambda 和函数代码之间的交互。

使用 pip 程序包管理器安装 Python 的运行时系统接口客户端

pip install awslambdaric

您也可以从中下载 Python 运行时接口客户端 GitHub。

以下示例演示了如何使用非 AWS 基本映像为 Python 构建容器映像。示例 Dockerfile 使用官方 Python 基本映像。Dockerfile 包含 Python 的运行时系统接口客户端。

要完成本节中的步骤,您必须满足以下条件:

要从非 AWS 基本映像创建容器映像
  1. 为项目创建一个目录,然后切换到该目录。

    mkdir example cd example
  2. 创建名为 lambda_function.py 的新文件。您可以将以下示例函数代码添加到文件中进行测试,也可以使用您自己的函数代码。

    例 Python 函数
    import sys def handler(event, context): return 'Hello from AWS Lambda using Python' + sys.version + '!'
  3. 创建名为 requirements.txt 的新文件。如果您使用的是上一步中的示例函数代码,则可以将文件留空,因为没有依赖项。否则,请列出每个必需的库。例如,如果您的函数使用的是 AWS SDK for Python (Boto3),则 requirements.txt 应如下所示:

    例 requirements.txt
    boto3
  4. 创建新 Dockerfile。以下 Dockerfile 使用官方 Python 基本映像而不是 AWS 基本映像。Dockerfile 包含运行时系统接口客户端,该客户端可使映像与 Lambda 兼容。以下示例 Dockerfile 将使用多阶段构建

    • FROM 属性设置为基本映像。

    • ENTRYPOINT 设置为您希望 Docker 容器在启动时运行的模块。在本例中,模块为运行时系统接口客户端。

    • CMD 设置为 Lambda 函数处理程序。

    例 Dockerfile
    # Define custom function directory ARG FUNCTION_DIR="/function" FROM python:3.12 as build-image # Include global arg in this stage of the build ARG FUNCTION_DIR # Copy function code RUN mkdir -p ${FUNCTION_DIR} COPY . ${FUNCTION_DIR} # Install the function's dependencies RUN pip install \ --target ${FUNCTION_DIR} \ awslambdaric # Use a slim version of the base Python image to reduce the final image size FROM python:3.12-slim # 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/python", "-m", "awslambdaric" ] # Pass the name of the function handler as an argument to the runtime CMD [ "lambda_function.handler" ]
  5. 使用 docker build 命令构建 Docker 映像。以下示例将映像命名为 docker-image 并为其提供 test 标签

    docker build --platform linux/amd64 -t docker-image:test .
    注意

    该命令指定了 --platform linux/amd64 选项,可确保无论生成计算机的架构如何,容器始终与 Lambda 执行环境兼容。如果打算使用 ARM64 指令集架构创建 Lambda 函数,请务必将命令更改为使用 --platform linux/arm64 选项。

使用运行时系统接口仿真器在本地测试映像。您可以将仿真器构建到映像中,也可以将其安装在本地计算机上。

在本地计算机上安装并运行运行时系统接口仿真器
  1. 在您的项目目录中,运行以下命令从中下载运行时接口仿真器(x86-64 架构) GitHub 并将其安装在本地计算机上。

    Linux/macOS
    mkdir -p ~/.aws-lambda-rie && \ curl -Lo ~/.aws-lambda-rie/aws-lambda-rie https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie && \ chmod +x ~/.aws-lambda-rie/aws-lambda-rie

    要安装 arm64 模拟器,请将上一个命令中的 GitHub 存储库 URL 替换为以下内容:

    https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie-arm64
    PowerShell
    $dirPath = "$HOME\.aws-lambda-rie" if (-not (Test-Path $dirPath)) { New-Item -Path $dirPath -ItemType Directory } $downloadLink = "https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie" $destinationPath = "$HOME\.aws-lambda-rie\aws-lambda-rie" Invoke-WebRequest -Uri $downloadLink -OutFile $destinationPath

    要安装 arm64 模拟器,请将 $downloadLink 替换为以下内容:

    https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie-arm64
  2. 使用 docker run 命令启动 Docker 映像。请注意以下几点:

    • docker-image 是映像名称,test 是标签。

    • /usr/local/bin/python -m awslambdaric lambda_function.handlerENTRYPOINT,后跟您 Dockerfile 中的 CMD

    Linux/macOS
    docker run --platform linux/amd64 -d -v ~/.aws-lambda-rie:/aws-lambda -p 9000:8080 \ --entrypoint /aws-lambda/aws-lambda-rie \ docker-image:test \ /usr/local/bin/python -m awslambdaric lambda_function.handler
    PowerShell
    docker run --platform linux/amd64 -d -v "$HOME\.aws-lambda-rie:/aws-lambda" -p 9000:8080 ` --entrypoint /aws-lambda/aws-lambda-rie ` docker-image:test ` /usr/local/bin/python -m awslambdaric lambda_function.handler

    此命令会将映像作为容器运行,并在 localhost:9000/2015-03-31/functions/function/invocations 创建本地端点。

    注意

    如果为 ARM64 指令集架构创建 Docker 映像,请务必使用 --platform linux/arm64 选项,而不是 --platform linux/amd64 选项。

  3. 将事件发布到本地端点。

    Linux/macOS

    在 Linux 和 macOS 中,运行以下 curl 命令:

    curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'

    此命令使用空事件调用函数并返回响应。如果您使用自己的函数代码而不是示例函数代码,则可能需要使用 JSON 负载调用函数。例如:

    curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'
    PowerShell

    在中 PowerShell,运行以下Invoke-WebRequest命令:

    Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{}' -ContentType "application/json"

    此命令使用空事件调用函数并返回响应。如果您使用自己的函数代码而不是示例函数代码,则可能需要使用 JSON 负载调用函数。例如:

    Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{"payload":"hello world!"}' -ContentType "application/json"
  4. 获取容器 ID。

    docker ps
  5. 使用 docker kill 命令停止容器。在此命令中,将 3766c4ab331c 替换为上一步中的容器 ID。

    docker kill 3766c4ab331c
将映像上传到 Amazon ECR 并创建 Lambda 函数
  1. 运行get-login-password命令将 Docker CLI 验证到您的 Amazon ECR 注册表。

    • --region 值设置为要在其中创建 Amazon ECR 存储库的 AWS 区域。

    • 111122223333 替换为您的 AWS 账户 ID。

    aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 111122223333.dkr.ecr.us-east-1.amazonaws.com
  2. 使用 create-repository 命令在 Amazon ECR 中创建存储库。

    aws ecr create-repository --repository-name hello-world --region us-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" } } }
  3. 从上一步的输出中复制 repositoryUri

  4. 运行 docker tag 命令,将本地映像作为最新版本标记到 Amazon ECR 存储库中。在此命令中:

    • docker-image:test 替换为 Docker 映像的名称和标签

    • 将 <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
  5. 运行 docker push 命令,以将本地映像部署到 Amazon ECR 存储库。确保存储库 URI 末尾包含 :latest

    docker push 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
  6. 如果您还没有函数的执行角色,请创建执行角色。在下一步中,您需要提供角色的 Amazon 资源名称(ARN)。

  7. 创建 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 \ --role arn:aws:iam::111122223333:role/lambda-ex
    注意

    只要映像与 Lambda 函数位于同一区域内,您就可以使用其他 AWS 账户中的映像创建函数。有关更多信息,请参阅 Amazon ECR 跨账户权限

  8. 调用函数。

    aws lambda invoke --function-name hello-world response.json

    应出现如下响应:

    { "ExecutedVersion": "$LATEST", "StatusCode": 200 }
  9. 要查看函数的输出,请检查 response.json 文件。

要更新函数代码,您必须重新构建映像,将新映像上传到 Amazon ECR 存储库,然后使用update-function-code命令将映像部署到 Lambda 函数。

对于如何从 Alpine 基本镜像创建 Python 镜像的示例,请参阅AWS博客上的 Lambda 容器镜像支持