DEV Community

Lino Espinoza πŸ‡΅πŸ‡ͺ
Lino Espinoza πŸ‡΅πŸ‡ͺ

Posted on • Updated on • Originally published at Medium

How to deploy your AWS Lambda based in containers with AWS ECR

Introduction

In previous working experiences, I was used to building and deploying AWS Lambda functions with zip files stored in AWS S3. I hadn’t had the opportunity to use containers instead, but there is a chance to try new ways of building solutions if you work in cloud development, right?

So, this post is about deploying an AWS Lambda function using container images stored in the AWS Elastic Container Registry. Let’s jump on it.

Prerequisites

  • AWS Command Line Interface, aka AWS CLI.
  • Docker
  • Node.js

πŸ’‘ To set up your AWS CLI, you can use Granted, as I explain in this blog post. πŸ™‚Β https://dev.to/linoespinoza/how-to-manage-multiple-aws-account-profiles-with-granted-5ho3

Creating a AWS Lambda Function

  1. Create a directory called aws-lambda-nodejs-container. Bear with me; I like to have a well-structured name on my folders, even if this is just an example. πŸ˜‰

    mkdir aws-lambda-nodejs-container 
    
  2. Create a simple Node.js project with npm inside that folder. You can accept the default options for this example.

    cd aws-lambda-nodejs-container
    npm init
    
  3. Create a new lambda function in a new file index.mjs

    export const lambdaHandler = async (event, context) => {
        const response = {
          statusCode: 200,
          body: JSON.stringify({
            message: 'This is a successful response from AWS Lambda',
          })
        };
    
        return response;
      };
    
  4. We need to create a simple Dockerfile with the configuration to create an image from the AWS EC Registry, COPY our lambda function code, RUN an install command, and finally, set the handler.

    FROM public.ecr.aws/lambda/nodejs:20-arm64
    
    COPY index.mjs ${LAMBDA_TASK_ROOT}
    
    CMD ["index.lambdaHandler"]
    
  5. Lets build our image, we are using an arm64 image. You can find a specific image in the Amazon ECR Public Gallery β†’ https://gallery.ecr.aws/lambda/nodejs

    docker build --platform linux/arm64 -t docker-image:test .
    

docker build

  1. If you want to test the image locally, docker is here to help you. Run your image like this:

    docker run --platform linux/arm64 -p 9000:8080 docker-image:test
    

docker run

  1. Then, invoke your lambda function:

    curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
    
  2. You will get something like this:

lambda invocation

Deploying the image to AWS ECR and your lambda function to AWS

To accomplish this, we need to create an AWS ECR Repository; we can do this through the AWS Console, AWS CLI, or the AWS CDK. Now, I’m going to use the AWS CLI; you must have experience using the CLI for your AWS tasks.

  1. First, we must authenticate the Docker CLI to your Amazon ECR Registry.

    1. In this example, I’m setting the us-east-1 as the AWS Region where I want to create the Amazon ECR repository
    2. Replace the string ****with your AWS Account ID.
    aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin <aws-account-id>.dkr.ecr.us-east-1.amazonaws.com
    
  2. Now it is time to create your AWS ECR Repository

    aws ecr create-repository --repository-name dev-repository --region us-east-1
    
  3. Grab the value from the repositoryUri attribute for the next step.

    {
        "repository": {
            "repositoryArn": "arn:aws:ecr:us-east-1:123456789012:repository/dev-repository",
            "registryId": "705941374709",
            "repositoryName": "dev-repository",
            "repositoryUri": "123456789012.dkr.ecr.us-east-1.amazonaws.com/dev-repository",
            "createdAt": "2024-02-17T16:02:31.898000-05:00",
            "imageTagMutability": "MUTABLE",
            "imageScanningConfiguration": {
                "scanOnPush": false
            },
            "encryptionConfiguration": {
                "encryptionType": "AES256"
            }
        }
    }
    
  4. We need to tag our local image. Also, it would be best if you replaced the with the value of the previous step.

    docker tag docker-image:test <ECRrepositoryUri>:latest
    
  5. Finally, we push our image to the AWS ECR repository.

    docker push <ECRrepositoryUri>:latest
    
  6. Create an execution role for the AWS Lambda function: https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-awscli.html#with-userapp-walkthrough-custom-events-create-iam-role

  7. Let’s create an AWS Lambda function.

    aws lambda create-function \
      --function-name nodejs-hello-world \
      --package-type Image \
      --code ImageUri=123456789012.dkr.ecr.us-east-1.amazonaws.com/dev-repository:latest \
      --role arn:aws:iam::123456789012:role/service-role/myNewFunction-role-67bgsgdp
    
  8. You will get something like this

    {
        "FunctionName": "nodejs-hello-world",
        "FunctionArn": "arn:aws:lambda:us-east-1:705941374709:function:nodejs-hello-world",
        "Role": "arn:aws:iam::705941374709:role/service-role/myNewFunction-role-67bgsgdp",
        "CodeSize": 0,
        "Description": "",
        "Timeout": 3,
        "MemorySize": 128,
        "LastModified": "2024-02-18T01:51:12.111+0000",
        "CodeSha256": "69b8fae1b0affd9d67c93341d0d3c07fbd85b702cf8cb97afaa1c32ffea4e331",
        "Version": "$LATEST",
        "TracingConfig": {
            "Mode": "PassThrough"
        },
        "RevisionId": "60613992-6bb8-4258-9e60-5ed3efefec6f",
        "State": "Pending",
        "StateReason": "The function is being created.",
        "StateReasonCode": "Creating",
        "PackageType": "Image",
        "Architectures": [
            "x86_64"
        ],
        "EphemeralStorage": {
            "Size": 512
        },
        "SnapStart": {
            "ApplyOn": "None",
            "OptimizationStatus": "Off"
        }
    }
    
  9. You can invoke the function

    aws lambda invoke --function-name nodejs-hello-world response.json
    

    And get a response like this:

    {
        "StatusCode": 200,
        "FunctionError": "Unhandled",
        "ExecutedVersion": "$LATEST"
    }
    

Remember, if you want to update the function code, you need to build the image again, upload to the Amazon ECR Repository, and then use the update-function-code command to deploy the image to the Lambda function

That’s it. I hope that you find this helpful.

See you in the next blog post!


HiπŸ‘‹πŸ»
My name is Lino, and I'm a builder who loves cloud technologies and serverless architectures. I write articles about these topics to share my knowledge and experience.
Don't forget to visit my Linktree to discover my projects 🫰🏻

Linktree: https://linktr.ee/linoespinoza

Follow me on dev.to for other articles πŸ‘‡πŸ»

Top comments (2)

Collapse
 
hebertrfreitas profile image
Hebert Freitas

Hey @linoespinoza, thanks for the post ! Maybe in the title of the post you mean "How to deploy your AWS Lambda based in containers with AWS ECR" and not ECS ?
I understand that is this case you are using ECR(Elastic Container Registry) as a docker image repository and not ECS (Elastic Container Service), am I right ?

Collapse
 
linoespinoza profile image
Lino Espinoza πŸ‡΅πŸ‡ͺ

Thanks for the feedback, @hebertrfreitas. I already changed it. :)