首页 > 文章列表 > 使用golang和docker构建的lambda替代图像

使用golang和docker构建的lambda替代图像

496 2024-02-07
问题内容

我正在尝试为运行 golang 处理程序的 lambda 创建一个 docker 映像,但该映像不来自 public.ecr.aws/lambda/go:1public.ecr.aws/lambda/provided:al2

我尝试按照 aws 文档中的步骤获取替代基本映像。

还有这个教程: https://hichaelmart.medium.com/using-container-images-with-aws-lambda-7ffbd23697f1

这根本行不通。 lambda 启动但不会处理任何请求。提出请求:

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

一去不复返。

如果我使用 public.ecr.aws/lambda/go:1 它工作正常。

据我所知,它可能缺少“运行时接口”,但他们的 go api 声称将其实现为处理程序代码的包装器。

这是我的 dockerfile

from alpine:3.16

add https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie /usr/bin/aws-lambda-rie
run chmod 755 /usr/bin/aws-lambda-rie

workdir /var/task

copy main ./

entrypoint ["/usr/bin/aws-lambda-rie", "/var/task/main"]

这是我的 lambda 处理程序

type myevent struct {
    name string `json:"name"`
}

func handlerequest(_ context.context, name myevent) (string, error) {
    return fmt.sprintf("hello %s!", name.name), nil
}

func main() {
    lambda.start(handlerequest)
}

服务请求的 docker 上的日志是

15 May 2023 06:34:03,985 [INFO] (rapid) exec '/var/task/main' (cwd=/var/task, handler=/var/task/main)
15 May 2023 06:34:08,178 [INFO] (rapid) extensionsDisabledByLayer(/opt/disable-extensions-jwigqn8j) -> stat /opt/disable-extensions-jwigqn8j: no such file or directory
15 May 2023 06:34:08,180 [INFO] (rapid) Configuring and starting Operator Domain
15 May 2023 06:34:08,182 [INFO] (rapid) Starting runtime domain
15 May 2023 06:34:08,188 [WARNING] (rapid) Cannot list external agents error=open /opt/extensions: no such file or directory
START RequestId: dfbc9842-2a7b-4a3e-bfd2-2434aa126f63 Version: $LATEST
15 May 2023 06:34:08,198 [INFO] (rapid) Starting runtime without AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN , Expected?: false
START RequestId: 5e0f07ac-46a3-42e0-8a60-851293544020 Version: $LATEST

任何有关我需要添加到 dockerfile 的内容的帮助将不胜感激。


正确答案


尚不清楚 main 二进制文件是如何构建的,但很可能它不是为 alpine 构建的。如果您检查容器的日志,您应该看到如下内容:

[warning] (rapid) first fatal error stored in appctx: runtime.invalidentrypoint
[error] (rapid) init failed error=fork/exec /var/task/main: no such file or directory invokeid=

解决办法是:

  • 替换基本 docker 映像以匹配 main 的构建目的;
  • 或为 alpine 重建 main 二进制文件。

下面的 dockerfile 显示了如何为 alpine 构建 main 二进制文件:

# ==== build stage ====
from golang:1.18.4-alpine3.16 as build

workdir /app

copy . .

run go build -o main .

# ==== final stage ====
from alpine:3.16.1

add https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie /usr/bin/aws-lambda-rie
run chmod 755 /usr/bin/aws-lambda-rie

workdir /var/task

copy --from=build /app/main ./

entrypoint ["/usr/bin/aws-lambda-rie", "/var/task/main"]

我也很好奇为什么 aws-lambda-rie 可以在 alpine 上运行。我发现它是用 cgo_enabled=0 构建的(请参阅 此处)。我们可以做同样的事情,因为简单的演示不需要 cgo:

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o main .

这个 main 二进制文件也适用于 alpine