Today I needed to update a couple Lambda functions from the Node 8 runtime to use the Node 10.x runtime. These functions required headless Chrome because they are used to take screenshots. Unfortunately, moving from the Node 8 runtime to 10x runtime is not a simple as it sounds, because AWS have decided to change the Linux environment which now excludes some files that Chromium requires to run.
As a reminder to myself, and for anyone else who might find it useful, I thought I’d document my setup here in a blog post. This post will assume you have the Serverless CLI set up and successfully deploying to AWS.
To start, I am using the following utilities:
- Serverless (serverless.com)
- puppeteer-core
- chrome-aws-lambda
- Chrome AWS Lambda Layer
Set up a Lambda Layer
Since the Chromium binary is quite large we don’t want to have to deploy it as part of the function. We need to put it in a Layer and use the Layer in our function.
Download this pre-built layer from GitHub ( chrome_aws_lambda.zip ) which contains the Chromium binary, and the chrome-aws-lambda and puppeteer-core npm packages.
In the AWS Console create a new layer and upload the above zip file.
Copy the ARN for the Layer.
Configure Serverless
You will need to add a layers setting in serverless.yml config for your function with the ARN you previously copied:
functions:
myFunctionName:
handler: myFunctionHandler
timeout: 30
memorySize: 2048
layers:
- ADD_LAYER_ARN_HERE
Set up your handler
Now you can use Puppeteer in your handler via the chrome-aws-lambda module. You don’t need to npm install this module because it will automatically be included from the Layer:
const chromium = require("chrome-aws-lambda");
module.exports = async (event, context) => {
try {
const browser = await chromium.puppeteer.launch({
headless: true,
executablePath: await chromium.executablePath,
args: chromium.args
});
const page = await browser.newPage();
await page.goto("https://somewebsite.com");
// ...do something, screenshot etc
await browser.close();
} catch (err) {
console.log(err);
// ...handle error
}
return {
statusCode: 200,
body: JSON.stringify({
success: true
})
};
}
Hopefully that should be everything you need to have Chromium loaded via a Layer and running on Lambda Node 10.x.
Hero photo by Max LaRochelle on Unsplash.