Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] Nodejs20-debian12 with aws-lambda-ric #1730

Open
McKnacker opened this issue Jan 10, 2025 · 3 comments
Open

[Question] Nodejs20-debian12 with aws-lambda-ric #1730

McKnacker opened this issue Jan 10, 2025 · 3 comments

Comments

@McKnacker
Copy link

Hey, we are currently running into issues while migrating onto an distroless image for our aws lambdas. I was following the docs from aws on how to use a non-AWS base image (https://docs.aws.amazon.com/lambda/latest/dg/nodejs-image.html#nodejs-image-clients).

Since the distroless image has removed package managers and everything else. NPM and NPX are not availabe. But I couldn't find any documentation what I could give as an entrypoint in the dockerfile for the aws-lambda-ric as an alternative. The documentation mentioned above expects the following entrypoint:

# Set runtime interface client as default command for the container runtime
ENTRYPOINT ["/usr/local/bin/npx", "aws-lambda-ric"]
# Pass the name of the function handler as an argument to the runtime
CMD ["index.handler"]

Do any of you have experience in what seems to be an edge case?

@loosebazooka
Copy link
Member

I'm a person with very little node knowledge, but could you just run the index.js in aws-lambda-ric directly?

The ENTRYPOINT provided by distroless is node, so don't modify that

and your CMD is ["<wherever aws-lambda-ric is>/index.js", "index.handler"]

@omBratteng
Copy link
Collaborator

I've played around with it, and it might not be possible with distroless because it expects /bin/sh to be able to fork a process
This is the Dockerfile I've concocted

FROM gcr.io/distroless/nodejs22-debian12:latest
COPY --from=public.ecr.aws/lambda/nodejs:22 /usr/local/bin/aws-lambda-rie /usr/local/bin/aws-lambda-rie
COPY --from=public.ecr.aws/lambda/nodejs:22 /var/runtime /var/runtime
ENV LAMBDA_TASK_ROOT=/var/task
WORKDIR /var/task

COPY index.js ${LAMBDA_TASK_ROOT}
ENTRYPOINT [ "/usr/local/bin/aws-lambda-rie" ]
CMD [ "/nodejs/bin/node", "/var/runtime/index.mjs" "index.handler" ]

Where index.js is

exports.handler = async (event) => {
  const response = {
    statusCode: 200,
    body: JSON.stringify('Hello from Distroless Lambda!'),
  };
  return response;
};

And running it as

docker run --rm -it -p 8080:8080 lambda

And I get the following logs

15 Jan 2025 23:12:54,738 [INFO] (rapid) exec '/bin/sh' (cwd=/var/task, handler=[ "/nodejs/bin/node", "/var/runtime/index.mjs" "index.handler" ])
START RequestId: ff3314bb-03a1-4640-ad58-e4d1a858f824 Version: $LATEST
15 Jan 2025 23:12:57,851 [INFO] (rapid) INIT START(type: on-demand, phase: init)
15 Jan 2025 23:12:57,851 [INFO] (rapid) The extension's directory "/opt/extensions" does not exist, assuming no extensions to be loaded.
15 Jan 2025 23:12:57,851 [INFO] (rapid) Starting runtime without AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN , Expected?: false
15 Jan 2025 23:12:57,851 [WARNING] (rapid) First fatal error stored in appctx: Runtime.InvalidEntrypoint
15 Jan 2025 23:12:57,851 [INFO] (rapid) INIT RTDONE(status: error)
15 Jan 2025 23:12:57,851 [INFO] (rapid) INIT REPORT(durationMs: 0.527000)
15 Jan 2025 23:12:57,851 [ERROR] (rapid) Init failed error=fork/exec /bin/sh: no such file or directory InvokeID=
15 Jan 2025 23:12:57,851 [WARNING] (rapid) Shutdown initiated: spindown
15 Jan 2025 23:12:57,851 [INFO] (rapid) Waiting for runtime domain processes termination
15 Jan 2025 23:12:57,851 [INFO] (rapid) INIT START(type: on-demand, phase: invoke)
15 Jan 2025 23:12:57,851 [INFO] (rapid) The extension's directory "/opt/extensions" does not exist, assuming no extensions to be loaded.
15 Jan 2025 23:12:57,851 [INFO] (rapid) Starting runtime without AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN , Expected?: false
15 Jan 2025 23:12:57,852 [WARNING] (rapid) First fatal error stored in appctx: Runtime.InvalidEntrypoint
15 Jan 2025 23:12:57,852 [INFO] (rapid) INIT RTDONE(status: error)
15 Jan 2025 23:12:57,852 [INFO] (rapid) INIT REPORT(durationMs: 0.909000)
15 Jan 2025 23:12:57,852 [INFO] (rapid) INVOKE START(requestId: edcda402-6476-44be-99cc-57d4d12d17f9)
15 Jan 2025 23:12:57,852 [ERROR] (rapid) Invoke failed error=fork/exec /bin/sh: no such file or directory InvokeID=edcda402-6476-44be-99cc-57d4d12d17f9
15 Jan 2025 23:12:57,852 [ERROR] (rapid) Invoke DONE failed: Runtime.InvalidEntrypoint
15 Jan 2025 23:12:57,852 [WARNING] (rapid) Reset initiated: ReleaseFail
15 Jan 2025 23:12:57,852 [INFO] (rapid) Waiting for runtime domain processes termination

If I somehow manage to sneak in /bin/sh, the following error comes

15 Jan 2025 23:09:28,724 [INFO] (rapid) exec '/bin/sh' (cwd=/var/task, handler=[ "/nodejs/bin/node", "/var/runtime/index.mjs" "index.handler" ])
START RequestId: 6bc08f86-e292-4168-b43d-41a00dd0bc3c Version: $LATEST
15 Jan 2025 23:09:33,008 [INFO] (rapid) INIT START(type: on-demand, phase: init)
15 Jan 2025 23:09:33,008 [INFO] (rapid) The extension's directory "/opt/extensions" does not exist, assuming no extensions to be loaded.
15 Jan 2025 23:09:33,008 [INFO] (rapid) Starting runtime without AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN , Expected?: false
sh: /var/runtime/index.mjs: unknown operand
15 Jan 2025 23:09:33,009 [WARNING] (rapid) First fatal error stored in appctx: Runtime.ExitError
15 Jan 2025 23:09:33,009 [WARNING] (rapid) Process runtime-1 exited: exit status 2
15 Jan 2025 23:09:33,009 [INFO] (rapid) INIT RTDONE(status: error)
15 Jan 2025 23:09:33,009 [INFO] (rapid) INIT REPORT(durationMs: 1.441000)
15 Jan 2025 23:09:33,009 [ERROR] (rapid) Init failed error=Runtime exited with error: exit status 2 InvokeID=
15 Jan 2025 23:09:33,009 [WARNING] (rapid) Shutdown initiated: spindown
15 Jan 2025 23:09:33,009 [INFO] (rapid) Waiting for runtime domain processes termination
15 Jan 2025 23:09:33,009 [INFO] (rapid) INIT START(type: on-demand, phase: invoke)
15 Jan 2025 23:09:33,009 [INFO] (rapid) The extension's directory "/opt/extensions" does not exist, assuming no extensions to be loaded.
15 Jan 2025 23:09:33,009 [INFO] (rapid) INIT REPORT(durationMs: 0.267000)
15 Jan 2025 23:09:33,009 [INFO] (rapid) INVOKE START(requestId: d7a3f34f-d788-4801-a36b-2561b6028c22)
15 Jan 2025 23:09:33,009 [ERROR] (rapid) Invoke failed error=Runtime exited with error: exit status 2 InvokeID=d7a3f34f-d788-4801-a36b-2561b6028c22
15 Jan 2025 23:09:33,009 [ERROR] (rapid) Invoke DONE failed: Sandbox.Failure
15 Jan 2025 23:09:33,009 [WARNING] (rapid) Reset initiated: ReleaseFail
15 Jan 2025 23:09:33,009 [INFO] (rapid) Waiting for runtime domain processes termination

If I use the :debug variant and run this to enter the shell

docker run --rm -it -p 8080:8080 --entrypoint /busybox/sh lambda

And then run this inside the container

/usr/local/bin/aws-lambda-rie /nodejs/bin/node /var/runtime/index.mjs index.handler

I can actually curl it and get a response (takes a few tries, not sure if that's how it works, not familiar with AWS lambda).

curl "http://localhost:8080/2015-03-31/functions/function/invocations" -d '{}'
{"statusCode":200,"body":"\"Hello from Distroless Lambda!\""}

@omBratteng
Copy link
Collaborator

With some extra digging, I've come up with this

FROM gcr.io/distroless/nodejs22-debian12:debug
COPY --from=public.ecr.aws/lambda/nodejs:22 /usr/local/bin/aws-lambda-rie /usr/local/bin/aws-lambda-rie
COPY --from=public.ecr.aws/lambda/nodejs:22 /var/runtime /var/runtime
ENV LAMBDA_TASK_ROOT=/var/task
WORKDIR /var/task

COPY index.js ${LAMBDA_TASK_ROOT}
COPY start.sh ${LAMBDA_TASK_ROOT}

ENTRYPOINT [ "/busybox/sh" ]
CMD [ "/var/task/start.sh" ]

start.sh file

/busybox/sh -c "/usr/local/bin/aws-lambda-rie /nodejs/bin/node /var/runtime/index.mjs index.handler"

I can now start the container

docker run --rm -it -p 8080:8080 lambda

And curl it

❯ curl "http://localhost:8080/2015-03-31/functions/function/invocations" -d '{}'
{"statusCode":200,"body":"\"Hello from Distroless Lambda!\""}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants