A Simpler Way to Manage Lambda Layers with NPM Dependencies
Here at QloudX, we do a lot of Node.js development. And given our obsession with serverless, a lot of that Node.js code ends up in Lambda functions.
Before Lambda layers came along, the NPM packages that our code depends on, had to be a part of the Lambda function ZIP. After layers were introduced, we did what everyone else did: add a layer resource to our SAM template that would create the layer & then attach this to the Lambda function.
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Resources:
NodeModulesLayer:
Type: AWS::Serverless::LayerVersion
Properties:
LayerName: node_modules
ContentUri: node_modules-layer/
The downside of this approach is that the layer is rebuilt every time our code is deployed. It also costs money to rebuild this layer (in CodeBuild), which hardly ever changes. So we came up with a better way!
GitHub Actions for Lambda Layers
We created a public GitHub repo, set up an action on it that would install all the NPM packages we want & deploy them to a Lambda layer in our AWS account. This forces us to think of layers as an application-independent resource that can be attached to Lambda functions across apps with the same NPM dependencies.
It’s also free since GitHub Actions run for free on public repositories (up to a limit). Whenever we need to add NPM packages to the layer, we simply add them to an environment variable for the Action & within minutes, a new version of the layer is deployed to AWS.
The Action workflow follows these steps:
- Start with an Ubuntu container.
- Set up Node.js on it.
- Create a directory named
nodejs
& install all needed NPM packages inside it. The namenodejs
is mandated by the Lambda layer spec. - ZIP up the
nodejs
directory. - And finally, use the AWS CLI to publish a layer version.
The entire Action workflow spec looks like this:
env:
NPM_PACKAGES: express mysql
on:
push:
branches: [ main ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v2.1.5
- run: mkdir nodejs && cd nodejs && npm install $NPM_PACKAGES && cd ..
- uses: TheDoctor0/zip-release@0.4.1
- uses: ItsKarma/aws-cli@v1.70.0
with:
args: >
lambda publish-layer-version
--layer-name node_modules
--compatible-runtimes nodejs
--zip-file fileb://release.zip
env:
AWS_DEFAULT_REGION: ap-south-1
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
How Can I Use This?
If you would like to use this solution, follow these steps:
- Fork this GitHub repo.
- Go to your fork’s settings & create the secrets
AWS_ACCESS_KEY_ID
&AWS_SECRET_ACCESS_KEY
. - Change the environment variable NPM_PACKAGES at the top of the Action spec with the NPM packages you need.
- As soon as you push this change, the workflow will run & deploy the layer to your account.
About the Author
Harish KM is an AWS Developer at QloudX. He is passionate about creating zero-maintenance fully-serverless cloud-native solutions in AWS. With 20+ cloud & IT certifications, he is an expert in a multitude of technologies, especially serverless.