How to Deploy AWS Lambda Container with AWS SAM
Learn about new AWS Lambda support for container images and how to use aws sam for setup and deploying docker container images to a lambda
What is AWS Lambda Container Images
During AWS re: Invent 2020, AWS announced a new feature to support container images for Lambda functions. This helps to package application code in a container image and run as the lambda function with container image size up to 10GB. The new feature removes the current size limitation which we have with the lambda and helps to support more use cases like using ML or data science code to run in Lambda. The current time out limit of 15minutes still exists.
In this blog, I'm writing on how to use AWS SAM for running locally a docker based Lambda function and also deploy it to an AWS account.
Docker Container Image Support for AWS Lambda
AWS has released base images for all the supported Lambda runtimes - Python, Node.js, Java, .NET, Go, Ruby to easily add the code and dependencies for developers to use. These images are built on top of Amazon Linux. AWS is also supporting arbitrary base images based on Alpine or Debian Linux with the only caveat that these images must implement the Lambda Runtime API.
Currently AWS ECR repository is the only supported image repository with the AWS Lambda.
Changes in AWS SAM Init Process and additional options
Lets deep dive into the AWS SAM init process and understand the new options,
As you see in the above image, there is a new package type option added to the sam init and selecting Image as the option will prompt to select the base image based on the runtime. For the custom-built images, the sam YAML template can be modified after the initialization. Along with this change, there is Dockerfile also generated when you select the option as image.
The generated template folder structure is as below,
The sam init operation generates a docker file which can be modified based on our needs,
#DockerFile Generated with the SAM init
FROM public.ecr.aws/lambda/nodejs:12
COPY app.js package.json ./
RUN npm install
# Command can be overwritten by providing a different command in the template directly.
CMD ["app.lambdaHandler"]
Comparison of AWS SAM templates with package type as Zip and Image
Now let's compare the sam yaml template which was generated with package types as zip and image.
Docker Images Supported
AWS has released the base docker images for all the lambda runtimes which are supported now. AWS is also supporting the custom base images and it can only be used if the AWS Lambda Runtime APIs are implemented on it. I will cover more about AWS Lambda Run time APIs in a different blog. You can check the aws lambda base images from the docker hub,
How to run Locally
Inorder to run the lambda locally, we run the sam build command,
sam build
This will build the docker image based on the Dockerfile and also tag it with the value provided in the Metadata of the template.yaml file.
Metadata:
DockerTag: nodejs12.x-v1
DockerContext: ./hello-world
Dockerfile: Dockerfile
Once the sam build command is successfully executed you can run docker image ls and it will list the new image which was built,
docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
helloworldfunction rapid-1.15.0 1d77f49d05a8 12 minutes ago 493MB
helloworldfunction nodejs12.x-v1 07f9a9d203da 13 minutes ago 477MB
public.ecr.aws/lambda/nodejs 12 c477d71b3ecb 9 days ago 465MB
Next step to invoke the lambda locally is to run command sam invoke,
sam local invoke
Invoking Container created from helloworldfunction:nodejs12.x-v1
Building image..............
Skip pulling image and use local one: helloworldfunction:rapid-1.15.0.
START RequestId: ede0b4c6-0151-4b37-8a7b-73f63a932268 Version: $LATEST
END RequestId: ede0b4c6-0151-4b37-8a7b-73f63a932268
REPORT RequestId: ede0b4c6-0151-4b37-8a7b-73f63a932268 Init Duration: 0.83 ms Duration: 141.81 ms Billed Duration: 200 ms Memory Size: 128 MB Max Memory Used: 128 MB
{"statusCode":200,"body":"{\"message\":\"hello world\"}"}%
Deployment Process
Deployment of the lambda docker is not a fully integrated processes. This requires following steps to be followed,
- Build the Docker Image Locally Run the docker image build command to create the docker image,
docker image build -t lambda-docker .
- Create a repository in ECR (if not available already) Create the ECR repository using the AWS cli or directly from the AWS Web Console. Once you create the ECR repository, you will get a ecr url based on the region and we can push the images to ECR repository using the docker command.
- Push the Image to the ECR
Use the AWS CLI to authenticate to AWS ECR. Then run the below command to tag the image with ecr url and push the image to ECR.
docker tag lambda-docker:latest 12345.dkr.ecr.sa-east-1.amazonaws.com/lambda-docker:latest
docker push 12345.dkr.ecr.sa-east-1.amazonaws.com/lambda-docker:latest
- Run the sam deploy command
sam deploy --stack-name dockerlambda --image-repository 12345.dkr.ecr.sa-east-1.amazonaws.com/lambda-docker:latest --profile my-profile --region us-east-1