You can package your Lambda function code and dependencies as a container image, using tools such as the Docker CLI. You can then upload the image to your container registry hosted on Amazon Elastic Container Registry (Amazon ECR).
AWS provides a set of open-source base images that you can use to create your container image. These base images include a runtime interface client to manage the interaction between Lambda and your function code.
Setup Pre-requisites:
1. Install AWS CLI v1 or v2. The command to invoke lambda will be different based on which version of CLI is used. Follow this doc to install CLI V2 – https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html
Check AWS CLI version – aws –version
AWS CLI v1 then the version will be something like – aws-cli/1.18.69
AWS CLI v2 version will be like – aws-cli/2.4.16
2. Configure CLI with IAM user who can access the account and perform actions.
3. Install Docker on Linux or Docker-Desktop on Windows. For this article, I have used Docker-desktop on Windows.
4. Create a role for the lambda and note the ARN of Role which is returned-
aws iam create-role --role-name lambda-container-image-execution --assume-role-policy-document '{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": {"Service": "lambda.amazonaws.com"}, "Action": "sts:AssumeRole"}] }'
Create ‘Hello World’ function (NodeJS) :
1. Create a new directory-
mkdir -p lambda cd lambda
2. Create an helloworld.js file in folder lambda-
exports.handler = async (event) => { const response = { statusCode: 200, body: JSON.stringify('Hello World'), }; return response; };
3. Initialize the NodeJS project. This will create a package.json file-
npm init -f
package.json
{ "name": "lambda", "version": "1.0.0", "description": "", "main": "helloworld.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }
4. Create Dockerfile with below content and build the Docker image –
FROM amazon/aws-lambda-nodejs:14 COPY helloworld.js package.json ./ RUN npm install CMD [ "helloworld.handler" ]
Now lambda folder will have three files – Dockerfile, helloworld.js, and package.json
Docker build command-
docker build -t helloworld .
5. This will download the Amazon-provided image amazon/aws-lambda-nodejs:14 and image will be created.
Test the Docker Image Locally:
1. Start the container using the image created-
docker run --rm -p 8080:8080 helloworld
2. Run the below command to invoke the lambda-
Using AWS CLI V2-
aws lambda invoke --region eu-west-1 --endpoint http://localhost:8080 --no-sign-request --function-name function --cli-binary-format raw-in-base64-out --payload '{"a":"b"}' output.txt
Using AWS CLI V1-
aws lambda invoke --region eu-west-1 --endpoint http://localhost:8080 --no-sign-request --function-name function --payload '{"a":"b"}' output.txt
Both commands should show output in output.txt file-
{"statusCode":200,"body":"\"Hello World\""}
NOTE: You may observe errors like – Invalid base64: “{“a”:”b”}” if the wrong version of aws cli is used.
Push Docker Image to AWS ECR-
1. Use the following command to log in to AWS ECR (change the region as required)-
docker login -u AWS -p $(aws ecr get-login-password --region eu-west-1) xxxxxxxxxxxxx.dkr.ecr.eu-west-1.amazonaws.com
2. Add a new tag to the helloworld image to push it to AWS ECR (ensure that repository by name helloworld is already created in AWS ERC)-
docker tag helloworld:latest 706949302588.dkr.ecr.eu-west-1.amazonaws.com/helloworld:latest docker push 706949302588.dkr.ecr.eu-west-1.amazonaws.com/helloworld:latest
Create Lambda function in AWS Lambda-
1. Now run this command to create the lambda function in your region. REPLACE the ARN of the Role and Image URI –
aws lambda create-function \ --package-type Image \ --function-name helloworld \ --role arn:aws:iam::xxxxxxxxxx:role/lambda-container-image-execution \ --code ImageUri=xxxxxxxxxxxxx.dkr.ecr.eu-west-1.amazonaws.com/helloworld:latest
2. Run the below command to invoke the lambda-
Using AWS CLI V2-
aws lambda invoke --region eu-west-1 --function-name helloworld --cli-binary-format raw-in-base64-out --payload '{"a":"b"}' output.txt
Using AWS CLI V1-
aws lambda invoke --region eu-west-1 --function-name helloworld --payload '{"a":"b"}' output.txt
Both commands should show output in output.txt file-
{"statusCode":200,"body":"\"Hello World\""}
Reference:
https://aws.amazon.com/blogs/aws/new-for-aws-lambda-container-image-support/
https://docs.aws.amazon.com/lambda/latest/dg/images-create.html