AWS CDK Construct: Lambda Fleet for Dockerfile

December 6th, 2020 463 Words

Using the AWS Cloud Development Kit, deploying a AWS Lambda function using Docker container images is pure gold. The installation of dependencies for Lambda functions always stressed me out. Regardless of using Node.js or Python, managing dependencies for AWS Lambda was never fun.

Dockerfile for Dependencies

I like the idea of using a Dockerfile for AWS Lambda to manage and install dependencies and persist immutable Artifacts. During Re:Invent 2020, AWS announced Container Image Support for AWS Lambda functions using the AWS Elastic Container Registry. The needed Dockerfile for Node.js can look like this:

FROM amazon/aws-lambda-nodejs:12

COPY package.json ./
RUN npm install
COPY handler.js ./

CMD [ "handler.run" ]

For Python, it may look like this:

FROM amazon/aws-lambda-python:3.8

COPY requirements.txt ./
RUN pip install -r requirements.txt
COPY handler.py ./

CMD [ "handler.run" ]

When orchestrating multiple AWS Lambda functions, just create a Dockerfile for every function, matching a function’s runtime requirements, and store them in a folder together with all other needed files:

src
 ├─ lambda-node-example
 │  ├─ Dockerfile
 │  ├─ handler.js
 │  └─ package.json
 └─ lambda-python-example
    ├─ Dockerfile
    ├─ handler.py
    └─ requirements.txt

CDK Construct: Lambda Fleet

Using this pattern for folders and files, everything to deploy all AWS Lambda functions can easily be build using the AWS Cloud Development Kit and published as a generic CDK Construct!

Install the cdk-lambda-fleet module from NPM and use it with the AWS Cloud Development Kit in TypeScript:

import * as path from "path";
import * as cdk from "@aws-cdk/core";

import { LambdaFleet } from "cdk-lambda-fleet";

export class FleetStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    new LambdaFleet(this, "Fleet", {
      path: path.resolve(__dirname, "../src"),
    });
  }
}

That’s all you need to configure, to build and push your docker images to AWS Elastic Container Registry using the AWS CDK and cdk-lambda-fleet.

Sources

You can find the source code on GitHub. The LambdaFleet construct looks up all folders in the given path and deploys a Lambda Function afterward.

import * as cdk from "@aws-cdk/core";
import * as Lambda from "@aws-cdk/aws-lambda";

import * as fs from "fs";
import * as camelcase from "camelcase";

export interface LambdaFleetProps {
  path: string;
}

export class LambdaFleet extends cdk.Construct {
  public functionList: { [key: string]: Lambda.Function } = {};

  constructor(scope: cdk.Construct, id: string, props: LambdaFleetProps) {
    super(scope, id);

    this.addFunctions(props.path);
  }

  private addFunctions(path: string) {
    const nodes = fs.readdirSync(path);

    nodes
      .filter((node) => fs.statSync(`${path}/${node}`).isDirectory())
      .forEach((name) => {
        const id = camelcase(name, { pascalCase: true });

        this.functionList[id] = new Lambda.DockerImageFunction(this, id, {
          code: Lambda.DockerImageCode.fromImageAsset(`${path}/${name}`),
        });

        new cdk.CfnOutput(this, `${id}Arn`, {
          value: this.functionList[id].functionArn,
        });
      });
  }
}

Of course, deploying a Lambda function involves more than just source code and a Dockerfile. You could extend this approach by adding a policy.json file for every function and update the Lambda.DockerImageCode.fromImageAsset to use it accordingly.


View on GitHub Source code is published using the MIT License.