happy New Year.
AWS Lambda now supports container images, so I created a Lambda to capture with Puppeteer.
According to the following article by Class Method, the local execution worked, but when I deployed it to Lambda, it didn't work. (Error at Chrome startup timing?)
I tried using Puppeteer with a Lambda container image | Developers.IO https://dev.classmethod.jp/articles/try-using-puppeteer-with-a-lambda-container-image/
The result of trial and error is here.
The whole has been uploaded here. https://github.com/moritalous/m5core2-yweather/tree/master/lambda
Dockerfile
Class Method was a combination of Google Chrome and puppeteer-core, but I wanted to run puppeteer alone, so I changed the package to install.
For the package to be installed, I referred to here.
Also install the Japanese font google-noto-sans-japanese-fonts
.
FROM amazon/aws-lambda-nodejs:12
RUN yum -y install libX11 libXcomposite libXcursor libXdamage libXext libXi libXtst cups-libs libXScrnSaver libXrandr alsa-lib pango atk at-spi2-atk gtk3 google-noto-sans-japanese-fonts
COPY app.js package*.json ./
RUN npm install
CMD [ "app.lambdaHandler" ]
Dependent libraries are puppeteer
and sharp
.
sharp
was added to resize the screenshot taken.
package.json
"dependencies": {
"puppeteer": "^5.5.0",
"sharp": "^0.27.0"
}
About args
specified in puppeteer.launch
For local execution, just specifying --no-sandbox
and --disable-setuid-sandbox
worked fine, but on Lambda I got an error.
Isn't it because the area other than the/tmp directory is read-only?
As a result of trial and error, it looks like this.
app.js
const browser = await puppeteer.launch({
headless: true,
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'-–disable-dev-shm-usage',
'--disable-gpu',
'--no-first-run',
'--no-zygote',
'--single-process',
]
});
I took a capture and resized it to PNG. Since it was returned via API Gateway, Base64 encode it and set it in the response.
app.js
buff = await page.screenshot({
clip: rect
});
buff = await sharp(buff).resize(320, 240).png().toBuffer();
base64 = buff.toString('base64');
await browser.close();
const response = {
statusCode: 200,
headers: {
'Content-Length': Buffer.byteLength(base64),
'Content-Type': 'image/png',
'Content-disposition': 'attachment;filename=weather.png'
},
isBase64Encoded: true,
body: base64
};
Lambda's container image support,
It seems that.
First I couldn't try it on GitHub Container Registry, then I couldn't try it on ECR public. ..
$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin [AWS account ID].dkr.ecr.ap-northeast-1.amazonaws.com
$ docker build -t [AWS account ID].dkr.ecr.ap-northeast-1.amazonaws.com/[Repository name]:latest .
$ docker push [AWS account ID].dkr.ecr.ap-northeast-1.amazonaws.com/[Repository name]:latest
Basically just follow the wizard.
One thing to note is that every time you push a new image to your ECR, you need to respecify the image to use with Lambda. It seems that you are looking at the value of the sha256 digest, and you have to specify it every time even if it is the latest tag.
Add a trigger on the Lambda screen. It's simple. With the REST API, I think there were various steps such as enabling binary support in the past, but I was able to return the PNG image without doing anything.
I tried to make the weather of Yahoo into a PNG image.
Recommended Posts