How to Deploy AWS Lambda Container with AWS SAM

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,

aws sam init option

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,

aws sam init option

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.

aws sam init option

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,

  1. Build the Docker Image Locally Run the docker image build command to create the docker image,
docker image build -t lambda-docker .
  1. 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.
  2. 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
  1. 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