How to deploy your AWS Lambda based in containers with AWS ECR
Tags: aws, lambda, docker, ecr
Published: 2024-02-18 02:08:23

## 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

<aside>
💡 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

</aside>

## 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. 😉
    
    ```bash
    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.
    
    ```bash
    cd aws-lambda-nodejs-container
    npm init
    ```
    
3. Create a new lambda function in a new file index.mjs

    
    ```tsx
    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.
    
    ```docker
    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
    
    ```bash
    docker build --platform linux/arm64 -t docker-image:test .
    ```
    
![docker build](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q1b054axwdofcpq22tw1.png)

    
6. If you want to test the image locally, docker is here to help you. Run your image like this:
    
    ```bash
    docker run --platform linux/arm64 -p 9000:8080 docker-image:test
    ```

![docker run](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ypixsmihsagsbq7eo03x.png)
    
7. Then, invoke your lambda function:
    
    ```bash
    curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
    ```
    
8. You will get something like this:
    

![lambda invocation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ozkbwa0gp6k9bate2fa.png)
    

## 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 **<aws-account-id>** string ****with your AWS Account ID.
    
    ```bash
    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
    
    ```bash
    aws ecr create-repository --repository-name dev-repository --region us-east-1
    ```
    
3. Grab the value from the repositoryUri attribute for the next step.
    
    ```bash
    {
        "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 <ECRrepositoryUri> with the value of the previous step.
    
    ```bash
    docker tag docker-image:test <ECRrepositoryUri>:latest
    ```
    
5. Finally, we push our image to the AWS ECR repository.
    
    ```bash
    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.
    
    ```bash
    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
    
    ```json
    {
        "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
    
    ```bash
    aws lambda invoke --function-name nodejs-hello-world response.json
    ```
    
    And get a response like this:
    
    ```json
    {
        "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](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) 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](https://linktr.ee/linoespinoza)

Follow me on dev.to for other articles 👇🏻
{% user linoespinoza %}