Package and deploy a Lambda function as a Docker container with AWS CDK
Tags: tutorial, programming, devops, cloud
Published: 2022-05-03 20:14:38

*Deploy a Serverless backend for Slack using Infrastructure-as-code (IaaC)*

One of my [previous blog post](https://dev.to/aws/using-aws-lambda-function-url-to-build-a-serverless-backend-for-slack-3j73) covered how to build a Serverless backend for Slack using by using [Lambda Function URL](https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html) as a webhook. Since I wanted to focus on the application itself, the infrastructure setup part was simplified - using AWS CLI, the function was packaged as a zip file, configured and finally a Function URL was created along with the required permissions.

In this blog, you will end up deploying the same solution, but this time using IaaC (Infrastructure-as-code) with [AWS Cloud Development Kit](https://docs.aws.amazon.com/cdk/v2/guide/home.html) (CDK) which is a framework for defining cloud infrastructure in code and provisioning it through AWS CloudFormation. You can choose from a list of supported programming languages (at the time of writing - TypeScript, JavaScript, Python, Java, C#/.Net, and Go (in developer preview)) to define your infrastructure components as code, just like you would with any other application!

You will learn how to use the [Go CDK library](https://pkg.go.dev/github.com/aws/aws-cdk-go/awscdk/v2) to deal with the infrastructure components:

- Define a Lambda function,
- Add a Lambda Function URL, and,
- Deploy the function as a Docker container (not a zip file)

By the end of this blog post, you should have the same setup as described in the [earlier blog](https://dev.to/aws/using-aws-lambda-function-url-to-build-a-serverless-backend-for-slack-3j73).

> The code is [available on GitHub](https://github.com/abhirockzz/awsome-slack-backend), as always!

## Pre-requisites

- [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) (if you do not already have one) and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources.
- Install [AWS CDK](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html#getting_started_install)
- Setup [Docker](https://docs.docker.com/get-docker/)
- [Install Go](https://go.dev/dl/)
- [Install Git](https://git-scm.com/downloads)
- [Create a Slack workspace](https://slack.com/create) if you don't have one.
- Create a GIHPY account (it's free!) and [create an app](https://developers.giphy.com/dashboard/?create=true). Each application you create will have its own API Key.

## CDK for IaaC - quick walkthrough

The CDK code is pretty succinct but it gets the job done! Let's go through it quickly.

First, we define the function and it's packaging format (as a Docker container):

```go
// environment variable for Lambda function
lambdaEnvVars := &map[string]*string{slackSecretEnvVar: jsii.String(slackSecret), giphyAPIKeyEnvVar: jsii.String(giphyAPIKey)}

function := awslambda.NewDockerImageFunction(stack, jsii.String("awsome-func-docker"), &awslambda.DockerImageFunctionProps{FunctionName: jsii.String(functionName), Environment: lambdaEnvVars, Code: awslambda.DockerImageCode_FromImageAsset(jsii.String("../function"), nil)})
```

Notice how [NewDockerImageFunction](https://pkg.go.dev/github.com/aws/aws-cdk-go/awscdk/v2@v2.22.0/awslambda#NewDockerImageFunction) has been used (traditionally, one would use [NewFunction](https://pkg.go.dev/github.com/aws/aws-cdk-go/awscdk/v2@v2.22.0/awslambda#NewFunction) and refer to a zip file for deployment). In this case, we point to the folder where our function code resides (using [DockerImageCode_FromImageAsset](https://pkg.go.dev/github.com/aws/aws-cdk-go/awscdk/v2@v2.22.0/awslambda#DockerImageCode_FromImageAsset)). 

For the function to be packaged as a Docker image, I used the [Go:1.x base image](https://gallery.ecr.aws/lambda/go) ([see Dockerfile](https://github.com/abhirockzz/awsome-slack-backend/blob/master/function/Dockerfile)). But, you can explore [other options](https://docs.aws.amazon.com/lambda/latest/dg/go-image.html) as well. During deployment, the Docker image is built locally, pushed to a [private ECR registry](https://docs.aws.amazon.com/AmazonECR/latest/userguide/Registries.html) and finally the Lambda function is created - all this, with a few lines of code!

The Function URL bit is straightforward using [NewFunctionUrl](https://pkg.go.dev/github.com/aws/aws-cdk-go/awscdk/v2@v2.22.0/awslambda#NewFunctionUrl):

```go
funcURL := awslambda.NewFunctionUrl(stack, jsii.String("awsome-func-url"), &awslambda.FunctionUrlProps{AuthType: awslambda.FunctionUrlAuthType_NONE, Function: function})
```

> For the purposes of this sample app, we're using `NONE` as the authentication type. This means that the Lambda function URL will be publicly accessible

## Create/Configure the command in Slack

Start by signing into your [Slack Workspace](https://slack.com/signin) and [creating a new Slack App](https://api.slack.com/apps/new).

Once that's done, create a Slash Command - head to your app's settings page, and then click the *Slash Commands* feature in the navigation menu. You'll be presented with a button marked *Create New Command*, and when you click on it, you'll see a screen where you'll be asked to define your new *Slash Command* with the required information.

Enter the required information:
- `/awsome` for the **Command**. 
- In **Request URL** section, enter a dummy URL for now e.g. https://comingsoon.com 

> This is temporary and will be replaced by the Lambda Function URL after deployment


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

Finally, install the app to your workspace - click the *Basic Information* feature in the navigation menu, choose *Install your app to your workspace* and click *Install App to Workspace*. This will install the app to your Slack workspace to test your app and generate the tokens you need to interact with the Slack API.

As soon as you finish installing the app, the *App Credentials* will show up on the same page. You need to grab your *Slack Signing Secret* from there

> Make a note of your app Signing Secret as you'll be using it later


![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8tp4dfpq4uzte30sylq6.png)

## Deploy the function using CDK and update Slack config

Clone the Github repo and move into the right directory:

```bash
git clone https://github.com/abhirockzz/awsome-slack-backend
cd awsome-slack-backend/function
```

Build the Go function:

```bash
GOOS=linux go build -o awsome
```

Deploy the function:

```bash
export SLACK_SIGNING_SECRET=<enter the slack signing secret>
export GIPHY_API_KEY=<enter the giphy API key>

cd ../cdk && cdk deploy
```

> Make a note of the Lambda Function URL that you receive as an output

Go back to the Slack and update the configuration to reflect the Lambda Function URL. 

Everything has been setup and configured. Now head over to your Slack workspace and invoke the Slack command you just configured! Try this:

```bash
/awsome serverless
```

## Cleanup

Once you're done, you can delete the function and related resources:

```bash
cdk destroy
```

## Wrap up!

In this blog post, we covered how to ease the deployment process for our Serverless backend using AWS CDK!