Golang Lambda Docker 从替代镜像构建

huangapple go评论90阅读模式
英文:

golang lambda docker from alternative image

问题

我正在尝试为运行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中添加什么的任何帮助,将不胜感激。

英文:

I'm trying to create a docker image for lambda running a golang handler, but which does not take from public.ecr.aws/lambda/go:1 or public.ecr.aws/lambda/provided:al2.

I tried to follow the steps on aws documentation for alternative base image.

And also this tutorial:
https://hichaelmart.medium.com/using-container-images-with-aws-lambda-7ffbd23697f1

It just won't work. The lambda starts but won't serve any requests. Making a request:

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

Never returns.

If I use public.ecr.aws/lambda/go:1 it works fine.

From what I've seen, it might be missing the "runtime interface" but their go api claims to be implementing it as a wrapper to the handler code.

This is my 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"]

This is my lambda handler

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)
}

The logs on the docker serving the requests are

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

Any help on what I need to add to the Dockerfile would be appreciated.

答案1

得分: 0

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二进制文件:

# ==== 构建阶段 ====
FROM golang:1.18.4-alpine3.16 as build

WORKDIR /app

COPY . .

RUN go build -o main .

# ==== 最终阶段 ====
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-riealpine上工作感到好奇。我发现它是使用CGO_ENABLED=0构建的(参见这里)。因为简单的演示不需要cgo,我们可以采用相同的方式构建:

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

这个main二进制文件也可以在alpine上工作。

英文:

It's not clear how the main binary is built, but it's most likely that it's not built for alpine. If you check the log of the container, you should see something like this:

[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=

The solutions are:

  • either replace the base docker image to match what main is built for;
  • or rebuild the main binary for alpine.

The Dockerfile below shows how to build the main binary for alpine:

# ==== 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"]

I'm also curious about why aws-lambda-rie works on alpine. And I found that it's built with CGO_ENABLED=0 (see here). We can do the same thing because the simple demo don't need cgo:

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

This main binary works on alpine too.

huangapple
  • 本文由 发表于 2023年5月15日 02:08:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76248996.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定