How to build container-based AWS Lambda applications

In this tutorial i would like to demonstrate how to create a simple container-based AWS Lambda function and deploy it using Pulumi.

What is a container based AWS Lambda ?

You may already know the concept of Function-as-a-Service and that you don't need servers when writing Lambda functions. With Lambda, you write your function, upload it to AWS, and it's ready to be executed, No servers to manage.

But the way we deployed our Lambda functions when Lambda was introduced back then in 2014 was by creating a ZIP archive from the code and it's dependencies and uploading it to AWS.

Under the hood, AWS unzipped our function and executed it inside a docker container, but we didn't have any control of it, well, until now at least.

AWS Lambda now supports packaging and deploying the lambda functions as container images.

The best way to explain it will be by seeing this in action by creating a container-based lambda function in the following example.

Our application will be a simple "screenshot" taker for a given website that you can define. In the example, we will take a screenshot of the front page of "hacker news" and upload the screenshot to AWS s3 on a daily basis.

So we basically need to implement and write the code for the lambda function and package it inside the docker container.

To deploy the container, we will first need to build the image and push it to a contaienr registry (we will use AWS ECR), and the last step will be to tell AWS Lambda itself to fetch the image that we just pushed from the repository and run it.

I will use Pulumi for the steps mentioned above for the deployment, It will help us define all those actions we want to perform (build image, push image and so on) as infrastructure as code and the best part of it is that we can choose our preferred language for it, we will use nodejs.

Here are the stack and packages that we are going to use:

  • PulumiPulumi, for deploying the lambda function as a container image.
  • Pupeteer, for actually taking the screenshots.
  • AWS s3 for storing the screenshots.
Dockerfile

our Docker file will be based on the base image public.ecr.aws/lambda/nodejs:14 as we need a nodejs base image that implements the AWS Lambda runtime API, so it's important to mentioned that not every base image can be used to Lambda, AWS provides us with many base images that already include the runtime for most of the Languages out there, and even if you couldn't find a base image for your needs, you can still take any image that you want and implement the AWS runtime API using a client SDK.

Other then installing pupeteer and chrome-aws-lambda with npm there is not much going on here. The code that we will use to take the screenshots lives inside app.js and we execute it's handler when starting the container.

The Screenshot taker code app.js

We are doing the following in our code:

  • we are launching pupeteer as a headless browser and visiting the website to take a screenshot.

  • next, we are uploading the screenshot taken to s3 using aws-sdk that is available to us.

lambda deployment as a container

now we have the functionality and we need to deploy the code as a lambda function and for that we can use pulumi with it's libraries that simplify the work for us.

if you want to know more about pulumi visit their website pulumi websitepulumi website you will need to make sure that you have pulumi installed on your machine.

Pulumi offers QuickStartes to allow us to start developing quickly and they offer a QuickStart for lambda as a container.

To start the pulumi project, run:

pulumi new https://github.com/pulumi/apps/lambda-containers.

move the Dockerfile we created to ./app/dockerfile and the app.js file to ./app/app.js. That will be the lambda handler that will be executed when the container runs.

In pulumi, you write you infrastructure as code, we will use typescript to define to the actions that we need. open the index.ts file in the root folder of the pulumi project and paste the following code:

The following resources will be created if we will run our Pulmui code

  • The docker image will be build and pushed to the ecr repository
  • iam Role and policies for lambda permissions will be created
  • the s3 bucket for saving the screenshots will be created
  • The lambda function will be created and because we define imageUri property in the aws.lambda.Function method, the lambda will run the image we just created
  • we also pass the bucket name as an environment variable to the functoin

You can deploy the application with pulumi up

Go to the AWS Lambda console and test if everything is working, you should se a screenshot file saved in the bucket.

In the next part of the tutorial I will cover the topic of how to run lambda and how to setup a Schedule for the lambda function.