英文:
golang lambda docker from alternative image
问题
我正在尝试为运行golang处理程序的lambda创建一个docker镜像,但不使用public.ecr.aws/lambda/go:1
或public.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-rie
在alpine
上工作感到好奇。我发现它是使用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 foralpine
.
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论