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

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

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

  • 使用 AWS 仅限操作系统的基础镜像

    Go 的实施方式与其他托管式运行时系统不同。由于 Go 本机编译为可执行的二进制文件,因此它不需要专用的语言运行时。使用仅限操作系统的基础映像为 Lambda 构建 Go 映像。要使映像与 Lambda 兼容,您必须在映像中包含 aws-lambda-go/lambda 软件包。

  • 使用非 AWS 基本映像

    您还可以使用其他容器注册表的备用基本映像,例如 Alpine Linux 或 Debian。您还可以使用您的组织创建的自定义映像。要使映像与 Lambda 兼容,您必须在映像中包含 aws-lambda-go/lambda 软件包。

提示

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

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

用于部署 Go 函数的 AWS 基础映像

Go 的实施方式与其他托管式运行时系统不同。由于 Go 本机编译为可执行的二进制文件,因此它不需要专用的语言运行时。使用仅限操作系统的基础映像将 Go 函数部署到 Lambda。

仅限操作系统
名称 标识符 操作系统 弃用日期 阻止函数创建 阻止函数更新

仅限操作系统的运行时系统

provided.al2023

Amazon Linux 2023

仅限操作系统的运行时系统

provided.al2

Amazon Linux 2

Amazon Elastic Container Registry Public Gallery:gallery.ecr.aws/lambda/provided

Go 运行时系统接口客户端

aws-lambda-go/lambda 程序包包括运行时接口的实施。有关如何在映像中使用 aws-lambda-go/lambda 的示例,请参阅 使用 AWS 仅限操作系统的基础镜像使用非 AWS 基本映像

使用 AWS 仅限操作系统的基础镜像

Go 的实施方式与其他托管式运行时系统不同。由于 Go 本机编译为可执行的二进制文件,因此它不需要专用的语言运行时。使用仅限操作系统的基础映像为 Go 函数构建容器映像。

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

al2023

仅限操作系统的运行时系统 Amazon Linux 2023 GitHub 上用于仅限操作系统的运行时系统的 Dockerfile

al2

仅限操作系统的运行时系统 Amazon Linux 2 GitHub 上用于仅限操作系统的运行时系统的 Dockerfile

有关这些基本映像的更多信息,请参阅 Amazon ECR Public Gallery 中的 provided

您必须在 Go 处理程序中包含 aws-lambda-go/lambda 程序包。此程序包实施 Go 的编程模型,包括运行时系统接口。

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

使用 provided.al2023 基本映像构建和部署 Go 函数
  1. 为项目创建一个目录,然后切换到该目录。

    mkdir hello cd hello
  2. 初始化一个新的 Go 模块。

    go mod init example.com/hello-world
  3. 添加 lambda 库作为新模块的依赖项。

    go get github.com/aws/aws-lambda-go/lambda
  4. 创建一个名为 main.go 的文件,然后在文本编辑器中打开它。这是适用于 Lambda 函数的代码。您可以使用以下示例代码进行测试,也可以将其替换为您自己的代码。

    package main import ( "context" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" ) func handler(ctx context.Context, event events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { response := events.APIGatewayProxyResponse{ StatusCode: 200, Body: "\"Hello from Lambda!\"", } return response, nil } func main() { lambda.Start(handler) }
  5. 使用文本编辑器在项目目录中创建一个 Dockerfile。以下示例 Dockerfile 将使用多阶段构建。这样便可在每个步骤中使用不同的基本映像。您可以使用一个映像(例如 Go 基本映像)来编译代码并构建可执行二进制文件。然后,您可以在最后的 FROM 语句中使用不同的映像(例如 provided.al2023)来定义部署到 Lambda 的映像。构建过程与最终部署映像分开,因此最终映像仅包含运行应用程序所需的文件。

    您可以使用可选的 lambda.norpc 标签排除 lambda 库的远程过程调用(RPC)组件。只有在使用已弃用的 Go 1.x 运行时系统时才需要 RPC 组件。排除 RPC 会减小部署包的大小。

    例 – 多阶段构建 Dockerfile
    注意

    确保您在 Dockerfile 中指定的 Go 版本(例如 golang:1.20)与用于创建应用程序的 Go 版本相同。

    FROM golang:1.20 as build WORKDIR /helloworld # Copy dependencies list COPY go.mod go.sum ./ # Build with optional lambda.norpc tag COPY main.go . RUN go build -tags lambda.norpc -o main main.go # Copy artifacts to a clean image FROM public.ecr.aws/lambda/provided:al2023 COPY --from=build /helloworld/main ./main ENTRYPOINT [ "./main" ]
  6. 使用 docker build 命令构建 Docker 映像。以下示例将映像命名为 docker-image 并为其提供 test 标签

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

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

使用运行时系统接口仿真器在本地测试映像。provided.al2023 基本映像还包括运行时系统接口仿真器。

在本地计算机上运行运行时系统接口仿真器
  1. 使用 docker run 命令启动 Docker 映像。请注意以下几点:

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

    • ./main 是您的 Dockerfile 中的 ENTRYPOINT

    docker run -d -p 9000:8080 \ --entrypoint /usr/local/bin/aws-lambda-rie \ docker-image:test ./main

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

  2. 在新的终端窗口中,使用 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!"}'
  3. 获取容器 ID。

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

    docker kill 3766c4ab331c
将映像上传到 Amazon ECR 并创建 Lambda 函数
  1. 运行 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-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 函数。

使用非 AWS 基本映像

您可以从非 AWS 基本映像为 Go 构建容器映像。以下步骤中的示例 Dockerfile 使用 Alpine 基本映像

您必须在 Go 处理程序中包含 aws-lambda-go/lambda 程序包。此程序包实施 Go 的编程模型,包括运行时系统接口。

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

使用 Alpine 基本映像构建和部署 Go 函数
  1. 为项目创建一个目录,然后切换到该目录。

    mkdir hello cd hello
  2. 初始化一个新的 Go 模块。

    go mod init example.com/hello-world
  3. 添加 lambda 库作为新模块的依赖项。

    go get github.com/aws/aws-lambda-go/lambda
  4. 创建一个名为 main.go 的文件,然后在文本编辑器中打开它。这是适用于 Lambda 函数的代码。您可以使用以下示例代码进行测试,也可以将其替换为您自己的代码。

    package main import ( "context" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" ) func handler(ctx context.Context, event events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { response := events.APIGatewayProxyResponse{ StatusCode: 200, Body: "\"Hello from Lambda!\"", } return response, nil } func main() { lambda.Start(handler) }
  5. 使用文本编辑器在项目目录中创建一个 Dockerfile。以下示例 Dockerfile 使用 Alpine 基本映像

    例 Dockerfile
    注意

    确保您在 Dockerfile 中指定的 Go 版本(例如 golang:1.20)与用于创建应用程序的 Go 版本相同。

    FROM golang:1.20.2-alpine3.16 as build WORKDIR /helloworld # Copy dependencies list COPY go.mod go.sum ./ # Build COPY main.go . RUN go build -o main main.go # Copy artifacts to a clean image FROM alpine:3.16 COPY --from=build /helloworld/main /main ENTRYPOINT [ "/main" ]
  6. 使用 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. 从项目目录中,运行以下命令以从 GitHub 下载运行时系统接口仿真器(x86-64 架构)并将其安装在本地计算机上。

    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 是标签。

    • /main 是您的 Dockerfile 中的 ENTRYPOINT

    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 \ /main
    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 ` /main

    此命令会将映像作为容器运行,并在 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 命令,以针对 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-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 函数。