CodeWithYou

Deploy Python Lambda functions with container images in AWS CDK

Published on
Authors
Deploy Python Lambda functions with container images in AWS CDK

Photo by Navi

This is a blog post about deploying Python Lambda functions with container images in AWS CDK.

You can deploy your Lambda function code as a container image.

AWS provides the following resources to help you build a container image for your Python function:

  • AWS base images for Lambda
  • Open-source runtime interface clients (RIC)
  • Open-source runtime interface emulator (RIE)

The workflow for a function defined as a container image includes these steps:

  1. Build your container image using the resources listed in this topic.
  2. Upload the image to your Amazon ECR container registry.
  3. Create the Lambda function or update the function code to deploy the image to an existing function.

But with AWS CDK, you can do this in a single step. Let see how to do this.

First, build a simple lambda function

#!/usr/bin/env python3

import wikipedia

def handler(event, context):
    print("{}".format(event))
    if event:
        result = wikipedia.page(event.get('wiki', 'los angeles'))
        return "{}".format(result.summary)
    else:
        return "You didn't tell me to look anything up, much sad."

And then, create a Dockerfile to build the image.

FROM public.ecr.aws/lambda/python:3.8

# ${LAMBDA_TASK_ROOT}
WORKDIR ${LAMBDA_TASK_ROOT}

# copy all python files to lamda working directory
COPY main.py .

# Copy requirements.txt to lamda working directory
COPY requirements.txt .
RUN pip3 install -r requirements.txt

# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
CMD [ "main.handler" ]

Note: Source code of this tutorial is available GitHub

Use AWS CDK to deploy the image

import { Stack, StackProps, CfnOutput } from 'aws-cdk-lib'
import { Construct } from 'constructs'
import * as lambda from 'aws-cdk-lib/aws-lambda'
import * as path from 'path'

export class CdkStarterStackStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props)

    const fn = new lambda.Function(this, 'TestContainerFunction', {
      code: lambda.Code.fromAssetImage(path.join(__dirname, '..', 'lambda'), {
        exclude: ['cdk.out'],
      }),
      handler: lambda.Handler.FROM_IMAGE,
      runtime: lambda.Runtime.FROM_IMAGE,
      architecture: lambda.Architecture.ARM_64,
    })

    const fnUrl = fn.addFunctionUrl({
      authType: lambda.FunctionUrlAuthType.NONE,
      cors: {
        // Allow this to be called from websites on https://example.com.
        // Can also be ['*'] to allow all domain.
        allowedOrigins: ['https://example.com'],
      },
    })

    // outputs the url of the function
    new CfnOutput(this, 'TestContainerFunctionURL', {
      value: fnUrl.url,
    })
  }
}

Let's over go what we did in the code snippet above.

  1. We created a lambda function from the code in the lambda directory.
  2. We created a lambda URL from the function. (this is for testing purpose).

Deploy stack and testing

npx cdk deploy --outputs-file ./cdk-outputs.json

After deploying the stack, we can test the function by visiting the URL exported by the stack.

Clean up

Don't forget to clean up the resources you created.

npx cdk destroy

Thanks for reading this tutorial. I hope you find it useful. If you have any questions, please feel free leave a comment.

Advertisement