avatarDenisse Damian

Summary

This article provides a comprehensive guide to setting up a CI/CD pipeline for deploying AWS Lambda functions using Docker and GitHub Actions.

Abstract

The guide outlines a step-by-step process for integrating Continuous Integration and Continuous Deployment (CI/CD) practices with AWS Lambda using Docker containers and GitHub Actions. It begins with dockerizing a Lambda function, which involves creating a new directory, writing the Lambda function code in index.js, and setting up a Dockerfile using an AWS base image. The tutorial then proceeds to demonstrate how to build, tag, and locally test the Dockerized Lambda function. Subsequent sections detail the setup of the AWS environment, including creating an ECR repository, defining an IAM policy for ECR access, and configuring AWS credentials securely within GitHub Secrets. The guide culminates in the creation of a GitHub Actions workflow defined in .github/workflows/deploy.yml, which automates the build, tag, and push processes for the Docker image to AWS ECR upon code commits to the master branch. Finally, the article explains how to create and deploy the Lambda function using the custom Docker image within the AWS Lambda console.

Opinions

  • The author emphasizes the importance of CI/CD in modern development practices for automating the software delivery process.
  • Dockerizing Lambda functions is recommended for better development and deployment consistency.
  • Testing the Dockerized Lambda function locally is highly recommended to ensure functionality before deployment.
  • The use of GitHub Secrets to store AWS access keys is suggested for secure handling of sensitive information.
  • The tutorial advocates for the use of GitHub Actions as a CI/CD tool due to its integration with GitHub repositories and ease of use.
  • The author considers the creation of an IAM policy with specific permissions for ECR as a best practice for security.
  • Optional steps, such as local testing and Lambda function testing post-deployment, are highlighted as important measures to verify the functionality of the deployment process.

Step-by-Step Guide to CI/CD for AWS Lambda with Docker and GitHub Actions

Photo by Alex Kulikov on Unsplash

Continuous Integration/Continuous Deployment (CI/CD) is an integral part of modern development practices, it allows you to automate and deploy. The aim is to automate the different steps in the software delivery process, from integration and testing phases to deployment to production. AWS Lambda is a serverless computing service that runs your code in response to events and automatically manages the computing resources for you.

In this tutorial we’ll cover:

  • Dockerizing the Lambda Function
  • Setting up CI/CD with GitHub Actions
  • Pushing the Docker image to AWS ECR (Elastic Container Registry)
  • Creating and Deploying the Lambda Function

Prerequisites:

  • AWS account and AWS CLI installed and configured.
  • GitHub account.
  • Basic knowledge of Docker and AWS Lambda.
  • Node.js (or any other runtime supported by AWS Lambda) installed on your local machine

Dockerizing the Lambda Function

1. Create a new folder for your Lambda function:

mkdir my-lambda-function
cd my-lambda-function

2. Create a file for your Lambda function, e.g., index.js:

touch index.js

Let’s add some code to our index.js file

exports.handler = async (event) => {
    return {
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!'),
    };
};

3. Create a Dockerfile:

touch Dockerfile

We are going to use an AWS base image for Lambda 💅

FROM public.ecr.aws/lambda/nodejs:16

COPY index.js ${LAMBDA_TASK_ROOT}
  
CMD [ "index.handler" ]

4. Build and tag the Docker Image

docker build -t my-lambda-function .

5. (Optional but highly recommend) Test locally

docker run -p 9000:8080 my-lambda-function:latest

On a separate terminal ping our endpoint.

 curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'

You should see the following output:

{"statusCode":200,"body":"\"Hello from Lambda!\""}

Setting up the AWS Environment

  1. Create an ECR repository and name it my-lambda
  2. Create an IAM policy to push to our ECR repository with the following permissions
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ecr:CompleteLayerUpload",
                "ecr:GetAuthorizationToken",
                "ecr:UploadLayerPart",
                "ecr:InitiateLayerUpload",
                "ecr:BatchCheckLayerAvailability",
                "ecr:PutImage"
            ],
            "Resource": "*"
        }
    ]
}

3. Create a user and attach the policy

4. Create Access Keys for the user

Select Third-party service when creating the keys

4. Add the Access Keys to your GitHub Repository

In the repository go to Settings>Secrets and Variables>New Repository secret

AWS Access Key
AWS Secret Access Key

Setting up CI/CD with GitHub Actions

  1. Create the repository for the Lambda function
git init
git add .
git commit -m "Initial commit"
git remote add origin [your-github-repo-url]
git push -u origin master

2. Create a .github/workflows/deploy.yml file in your repo:

name: Deploy Lambda Function

on:
  push:
    branches:
      - master

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v2

    - name: Configure AWS Credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: [your-aws-region]

    - name: Build Docker Image
      run: docker build -t my-lambda .

    - name: Tag Docker Image
      run: docker tag my-lambda:latest ${{ steps.login-ecr.outputs.registry }}/my-lambda:latest

    - name: Push Docker Image to ECR
      run: docker push ${{ steps.login-ecr.outputs.registry }}/my-lambda:latest

Code Explanation:

  1. Checkout: This step checks out your repository under $GITHUB_WORKSPACE, so the workflow can access it.
  2. Configure AWS Credentials: This step will access the secrets we created in the previous step to login to AWS
  3. Logging into Amazon ECR: After setting up the AWS credentials, this phase utilizes a GitHub Action to authenticate with the Amazon ECR repository.
  4. Building and Uploading the Docker Image to AWS ECR: Leveraging the successful AWS login from the previous step, we retrieve the ECR registry details. The ECR repository name, then used to dynamically construct and upload a Docker image to AWS. In the code snippet provided, the image is tagged as latest .

Creating and Deploying the Lambda Function

  1. Go to the AWS Lambda console and create a new Lambda function.
  2. For the runtime, select Custom runtime in a Docker image.
  3. Specify my-lambda ECR repository, select the latest image
Create Lambda Function

4. (Optional but highly recommend) Test

Send an empty event to your lambda and you should have the following output

{
  "statusCode": 200,
  "body": "\"Hello from Lambda!\""
}
Lambda
AWS
Ci Cd Pipeline
Docker
Recommended from ReadMedium