Create Lambda Layers with AWS CLI - Complete Guide

avatar

Borislav Hadzhiev

Sat Sep 18 20215 min read

banner

Photo by Sam Barber

Table of Contents #

  1. Creating the Role for the Lambda Function
  2. Creating the Lambda Function with AWS CLI
  3. Packaging and Deploying Lambda Layers with AWS CLI
  4. Attaching Layers to a Lambda Function with AWS CLI

Creating the Role for the Lambda Function #

In this article we will create a node.js lambda function with 2 layers using AWS CLI.

The layers consist of:

  • a 3rd party library, called date-fns
  • our own helper function

Before creating the lambda function, we must create a role for it. The role needs to have a trust policy that allows the lambda service to assume it.

The code for this article is available on GitHub

Save the following json into a trust-policy.json file:

trust-policy.json
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }

Open your terminal in the directory where you stored the trust-policy.json file and pass it to the create-role command:

shell
aws iam aws iam create-role --role-name lambda-layers-role --assume-role-policy-document file://trust-policy.json

create lambda role

Copy and paste the role arn into a notepad, because we'll need it when creating the lambda function.

Next, attach a policy to the role, which grants permissions to log to cloudwatch:

shell
aws iam attach-role-policy --role-name lambda-layers-role --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

attach policy to role

Creating the Lambda Function with AWS CLI #

Now that we have the role, let's create the node.js lambda function, create an index.js file with the following code:

The code for this article is available on GitHub
index.js
const {format} = require('date-fns'); const {double} = require('calc'); exports.handler = async event => { const response = { statusCode: 200, body: JSON.stringify({ today: format(new Date(), "'Today is a' eeee"), doubled: double(15), }), }; return response; };

The function imports the layers and uses them to form the response.

Let's zip the lambda function code so we can create it using the CLI:

shell
zip -r9 lambda.zip index.js

zip lambda function

And finally, let's create the function using the AWS CLI, open your terminal in the directory where you stored the lambda.zip file and run the create-function command:

shell
aws lambda create-function --function-name layers-function --runtime nodejs14.x --zip-file fileb://lambda.zip --handler index.handler --role "arn:aws:iam::YOUR_ACCOUNT_NUMBER:role/lambda-layers-role"

create lambda function

Packaging and Deploying Lambda Layers with AWS CLI #

At this point we've created the node.js function, however we haven't packaged and deployed the layers it makes use of.

The directory paths for the layers are kind of tricky, because lambda expects a specific folder structure.

The code for this article is available on GitHub

Create the following folders and files in the directory where you stored the lambda's index.js file:

shell
layers calc nodejs node_modules calc.js date-fns nodejs package.json index.js

If you get confused about the folder structure, check out the github repository.

Let's take care of the calc layer first. Open the calc.js file and enter the following code in it:

layers/calc/nodejs/node_modules/calc.js
exports.double = (number) => { return number * 2; }

The file exports a utility function that we can include as a layer and reuse in multiple lambda functions.

Note that in most projects node_modules is added to .gitignore, since we are storing a helper function, in the node_modules directory and not a 3rd party package, make sure to exclude the file from your .gitignore, e.g. by adding the following line to your .gitignore - !layers/calc/**/node_modules.

Now let's take care of the layer that imports a 3rd party package. Open your terminal in the layers/date-fns/nodejs directory and run the following commands:

layers/date-fns/nodejs
# in the layers/date-fns/nodejs directory npm init -y npm install date-fns@2.24.0

Your folder structure should look like:

layers folder structure

At this point we are ready to zip the code for the layers, create them and add them to the lambda function.

Let's zip the code for the calc layer first, open your terminal in the layers/calc directory and run the zip command:

layers/calc
# in the layers/calc directory zip -r9 calc-layer.zip .

zip calc layer

To create the calc layer use the publish-layer-version command from the /layers/calc directory:

layers/calc
aws lambda publish-layer-version --layer-name calc-layer --description "added double fn" --zip-file fileb://calc-layer.zip --compatible-runtimes nodejs10.x nodejs12.x nodejs14.x

create calc layer

Copy and paste the value of the LayerVersionArn property in a notepad, because we will need it when attaching the layer to the lambda function. The LayerVersionArn will look something like: "arn:aws:lambda:YOUR_REGION:YOUR_ACCOUNT_ID:layer:calc-layer:1"

Let's also zip and publish the date-fns layer. Open your terminal in the layers/date-fns directory and run the zip command:

layers/date-fns
# in the layers/date-fns directory zip -r9 date-fns-layer.zip .

To create the date-fns layer, open your terminal in the layers/date-fns directory and run the publish-layer-version command:

layers/date-fns
# in the layers/date-fns directory aws lambda publish-layer-version --layer-name date-fns-layer --description "add date-fns library" --zip-file fileb://date-fns-layer.zip --compatible-runtimes nodejs10.x nodejs12.x nodejs14.x
Copy and paste the value of the LayerVersionArn property in a notepad, because we will need it when attaching the layer to the lambda function. The LayerVersionArn will look something like: "arn:aws:lambda:YOUR_REGION:YOUR_ACCOUNT_ID:layer:date-fns-layer:1"

create date fns layer

Attaching Layers to a Lambda Function with AWS CLI #

At this point, we've created the layers and all we have to do is attach the layers to the lambda function.

We'll need the LayerVerionArns for both of the layers. In case you didn't copy the LayerVersionArns, run the following commands to retrieve them:

shell
aws lambda list-layer-versions --layer-name calc-layer --query "LayerVersions[*].LayerVersionArn" aws lambda list-layer-versions --layer-name date-fns-layer --query "LayerVersions[*].LayerVersionArn"

The command returns a list of all the LayerVersionArns of a layer, just pick the latest version if you have multiple.

Finally, let's add the layers to the lambda function and test if everything works as expected.

Run the update-function-configuration command, setting the --layers parameter as our space-separated LayerVersionArns.

shell
aws lambda update-function-configuration --function-name layers-function --layers "CALC_LAYER_VERSION_ARN" "DATE_FNS_LAYER_VERSION_ARN"

add layers to lambda

Let's test if everything works as expected, invoke the lambda function, storing the response in a response.json file:

shell
aws lambda invoke --function-name layers-function response.json

invoke lambda with layers

The lambda function's response shows that the layers work as expected.

Note that the update-function-configuration command, which we used to attach the layers to the function simply replaces existing function's layers (if any), with the new layers we specified.

To be on the safe side, we can list the existing function's layers and include the ARNs in the update-function-configuration command.

To list the function's layers, run the get-function-configuration command:

shell
aws lambda get-function-configuration --function-name layers-function --query "{layers: Layers, revisionId: RevisionId}"

list lambda layers

We used the --query parameter to limit the output to relevant to us properties:

  • the ARNs of the layers

  • the revisionId, which can be included in the update-function-configuration command and is only used when multiple people work on the same lambda function.

    It allows us to be sure that no one of our colleagues updated the function in the time window we listed the function's layers and updated them. In other words it helps us avoid race conditions.

In the case we wanted to add layers to the lambda function and not replace the existing layers, we would copy the existing function's layer ARNs and include it in the update-function-configuration command.

Further Reading #

Join my newsletter

I'll send you 1 email a week with links to all of the articles I've written that week

Buy Me A Coffee