aws / aws-lambda-runtime-interface-emulator

Apache License 2.0
950 stars 99 forks source link

image entrypoint documentation #24

Closed diegosasw closed 3 years ago

diegosasw commented 3 years ago

I'm trying to run a local container that has been created as a lambda dotnet 5 image following an Amazon template. In other words, I have a dotnet 5 project with a AWS lambda function which I have created with

dotnet new -i Amazon.Lambda.Templates
dotnet new serverless.image.AspNetCoreWebAPI -n LambdaDotNet5
dotnet build -c Release
dotnet publish -c Release

This creates a dotnet project with a simple Dockerfile (notice there is no entry point or anything) and compiles it and publishes its artifacts in a folder.

FROM public.ecr.aws/lambda/dotnet:5.0
WORKDIR /var/task
COPY "bin/Release/net5.0/publish"  .

Notice by default this line was COPY "bin/Release/net5.0/linux-x64/publish" . but my dotnet publish -c Release places it under publish folder, without the linux-x64 part. Now I follow the instructions described and I can build a docker image locally

docker build -t lambda-dotnet .

Using a git-bash linux-like terminal in Windows I run

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

and I can see the emulator properly downloaded

ls -la ~/.aws-lambda-rie/aws-lambda-rie
-rw-r--r-- 1 diego.martin 1049089 8155136 Feb 22 13:32 /c/Users/diego.martin/.aws-lambda-rie/aws-lambda-rie

Now I want to run the emulator with my container, so here's where I'm not sure what am I doing or what may be the problem

docker run -d -v ~/.aws-lambda-rie:/aws-lambda -p 9000:8080 --entrypoint /aws-lambda/aws-lambda-rie lambda-dotnet:latest

Notice I don't specify any entrypoint because I don't have any in my image. So the output is

54b355026ba16fc12d5884b38ff4f9cb481e007ac1cdbc222f17666891c9aa94
docker: Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "C:/Users/diego.martin/AppData/Local/Programs/Git/aws-lambda/aws-lambda-rie": stat C:/Users/diego.martin/AppData/Local/Programs/Git/aws-lambda/aws-lambda-rie: no such file or directory: unknown.

What am I missing and what would be the command to run the RIE with my lambda container?

diegosasw commented 3 years ago

I've created a repo to reproduce it https://gitlab.com/sunnyatticsoftware/sandbox/lambda-dotnet5-webapi

carlzogh commented 3 years ago

Hey @diegosasw - thanks for reaching out.

Lambda base images already include the RIC and provide a seamless local experience by abstracting away most of it behind the predefined /lambda-entrypoint.sh ENTRYPOINT script of these base images. The AWS docs on Testing Lambda container images locally describe how you can run and invoke your Lambda function container image locally. For the .NET base images, this is also documented on the public gallery page for the Lambda .NET base images' repository (https://gallery.ecr.aws/lambda/dotnet) under the Usage tab.

Essentially in your case, you should also define the CMD directive in your Dockerfile as your function handler, eg:

# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
CMD [ "MyProject::MyFunction.Function::FunctionHandler" ]

If the CMD is defined in your container image, you can run your function locally through the embedded RIE in the base images as such:

docker run -p 9000:8080 diegosasw/my-project

Otherwise if you'd rather not define the handler in your Dockerfile, this can be passed in as a function override if running in Lambda, or as a parameter in the docker run command if running locally, eg:

docker run -p 9000:8080 diegosasw/my-project "MyProject::MyFunction.Function::FunctionHandler"

After your container is started, in a separate terminal, you can then locally invoke the function using cURL:

curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'

Regardless of whether the RIE is included in the base image or not, you should also be able to mount it and use it as you've described (and how it is documented in this project's README).

From your snippets, I can see that the RIE binary does not have the x (executable) permission flags set:

ls -la ~/.aws-lambda-rie/aws-lambda-rie
-rw-r--r-- 1 myusername 1049089 8155136 Feb 22 13:32 /c/Users/myusername /.aws-lambda-rie/aws-lambda-rie

An executable file is one that has the x flag set (eg. -rwxr-xr-x).

Seeing as you're running the correct command to set the executable flag (ie. chmod +x ~/.aws-lambda-rie/aws-lambda-rie), I suspect this might have something to do with the format of your Windows drive. Quoting the Cygwin documentation on File permissions:

On FAT or FAT32 filesystems, files are always readable [...]

On NTFS, file permissions are evaluated using the Access Control Lists (ACLs) attached to a file. This can be switched off by using the "noacl" option to the respective mount point in the /etc/fstab or /etc/fstab.d/$USER file.

So I'd look at the drive format on your Windows host and see how the Linux-like terminal that you're using handles file permissions for that format. Alternatively, you can do this to your Dockerfile as documented in the AWS docs section about Build RIE into your base image.

diegosasw commented 3 years ago

Brilliant! Much appreciated. I updated my repo with the instructions as per your explanation and it's all working perfectly.

Haven't tested it by mounting it but I also suspect it has something to do with the Windows git-bash console (not really a linux file system). I'll give it a try later with a WSL2 linux distro though.