chrome-aws-lambda
chrome-aws-lambda copied to clipboard
[REQUEST] Include ARM_64 binaries
What would you like to have implemented?
Include ARM_64 architecture supported binaries
Why would it be useful?
AWS Lambda now supports ARM_64 architecture but chrome-aws-lambda only ships with x86_64 binaries and is incompatible with this new Lambda feature.
Or am I misunderstanding something?
I compiled Chromium 97.0.4666.0 for ARM64 together with some minor patches to get it working on AWS Lambda (NodeJS 14).
Steps to get it working:
- ~~Download this zip file.~~ Link expired, see info below.
- Use it as a Lambda layer.
- The binary will then be in
/opt/chromium
. - I also added the required files
libGLESv2.so
,libEGL.so
,libsqlite3.so.0
,libsoftokn3.so
,libnss3.so
,libexpat.so.1
and some fonts. - You don't need this library (chrome-aws-lambda). Via playwright you use the following command in your Lambda code (I have not tested with puppeteer but that command will probably not differ much):
const browser = await chromium.launch({
executablePath: "/opt/chromium",
args: ["--no-zygote", "--in-process-gpu", "--single-process"]
});
- Set the environment variable
FONTCONFIG_PATH
:/opt/fonts
.
Let me know if you have troubles.
Thank you @lifesaverluke for your help but unfortunately I wasn't able to to get this working. I used the the binaries as Lambda layer but on every invoke I receive an error:
{
"errorType": "Error",
"errorMessage": "Failed to launch the browser process! spawn /opt/chromium EACCES\n\n\nTROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md\n",
"stack": [
"Error: Failed to launch the browser process! spawn /opt/chromium EACCES",
"",
"",
"TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md",
"",
" at onClose (/var/task/node_modules/puppeteer-core/lib/cjs/puppeteer/node/BrowserRunner.js:197:20)",
" at ChildProcess.<anonymous> (/var/task/node_modules/puppeteer-core/lib/cjs/puppeteer/node/BrowserRunner.js:189:85)",
" at ChildProcess.emit (events.js:400:28)",
" at Process.ChildProcess._handle.onexit (internal/child_process.js:275:12)",
" at onErrorNT (internal/child_process.js:467:16)",
" at processTicksAndRejections (internal/process/task_queues.js:82:21)"
]
}
EACCES refers to permission issue on OS so I made a new Lambda layer archive where with -rwxrwxrwx
permissons on all files, and still the same error exists.
The browser init I use is:
const initBrowser = async () => {
return await chromium.puppeteer.launch({
defaultViewport: chromium.defaultViewport,
//executablePath: await chromium.executablePath,
executablePath: "/opt/chromium",
headless: chromium.headless,
ignoreHTTPSErrors: true,
acceptInsecureCerts: true,
dumpio: true,
args: [...chromium.args,
'--ignore-certificate-errors',
'--ignore-certificate-errors-spki-list',
'--enable-features=NetworkService']
});
};
And I also tried with those "--no-zygote", "--in-process-gpu", "--single-process" appended. Maybe there are some lib files missing from the package?
Thank you @lifesaverluke for your help but unfortunately I wasn't able to to get this working. I used the the binaries as Lambda layer but on every invoke I receive an error:
{ "errorType": "Error", "errorMessage": "Failed to launch the browser process! spawn /opt/chromium EACCES\n\n\nTROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md\n", "stack": [ "Error: Failed to launch the browser process! spawn /opt/chromium EACCES", "", "", "TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md", "", " at onClose (/var/task/node_modules/puppeteer-core/lib/cjs/puppeteer/node/BrowserRunner.js:197:20)", " at ChildProcess.<anonymous> (/var/task/node_modules/puppeteer-core/lib/cjs/puppeteer/node/BrowserRunner.js:189:85)", " at ChildProcess.emit (events.js:400:28)", " at Process.ChildProcess._handle.onexit (internal/child_process.js:275:12)", " at onErrorNT (internal/child_process.js:467:16)", " at processTicksAndRejections (internal/process/task_queues.js:82:21)" ] }
EACCES refers to permission issue on OS so I made a new Lambda layer archive where with
-rwxrwxrwx
permissons on all files, and still the same error exists.The browser init I use is:
const initBrowser = async () => { return await chromium.puppeteer.launch({ defaultViewport: chromium.defaultViewport, //executablePath: await chromium.executablePath, executablePath: "/opt/chromium", headless: chromium.headless, ignoreHTTPSErrors: true, acceptInsecureCerts: true, dumpio: true, args: [...chromium.args, '--ignore-certificate-errors', '--ignore-certificate-errors-spki-list', '--enable-features=NetworkService'] }); };
And I also tried with those "--no-zygote", "--in-process-gpu", "--single-process" appended. Maybe there are some lib files missing from the package?
Weird! I'll investigate and send an update here as soon as I've found the problem.
@villetuomaala Fixed!
For some reason there was an extra /opt/chromium/chromium dir in the zipfile when used as layer, resulting in the error that you mentioned.
I uploaded a new version with a fix :-) Let me know if this works!
I'm trying this with [email protected]
on Lambda and I'm seeing this error when attempting to launch the browser:
Error: Protocol error (Target.setDiscoverTargets): Target closed.
at /opt/nodejs/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:71:63
at new Promise (<anonymous>)
at Connection.send (/opt/nodejs/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:70:16)
at Function.create (/opt/nodejs/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Browser.js:118:26)
at ChromeLauncher.launch (/opt/nodejs/node_modules/puppeteer-core/lib/cjs/puppeteer/node/Launcher.js:109:56)
I'm also seeing this when re-attempting the launch:
ErrorEvent {
target: WebSocket {
_events: [Object: null prototype] { open: [Function], error: [Function] },
_eventsCount: 2,
_maxListeners: undefined,
_binaryType: 'nodebuffer',
_closeCode: 1006,
_closeFrameReceived: false,
_closeFrameSent: false,
_closeMessage: '',
_closeTimer: null,
_extensions: {},
_protocol: '',
_readyState: 3,
_receiver: null,
_sender: null,
_socket: null,
_bufferedAmount: 0,
_isServer: false,
_redirects: 0,
_url: 'ws://127.0.0.1:36089/devtools/browser/0fd89080-24a1-439e-955a-84de431d7f9e',
_req: null,
[Symbol(kCapture)]: false
},
type: 'error',
message: 'socket hang up',
error: Error: socket hang up
at connResetException (internal/errors.js:628:14)
at Socket.socketOnEnd (_http_client.js:499:23)
at Socket.emit (events.js:412:35)
at Socket.emit (domain.js:470:12)
at endReadableNT (internal/streams/readable.js:1317:12)
at processTicksAndRejections (internal/process/task_queues.js:82:21) {
code: 'ECONNRESET'
}
}
These are the arguments I'm using:
[
'--no-sandbox',
'--no-zygote',
'--disable-gpu',
'--ignore-certificate-errors',
'--allow-running-insecure-content',
'--disable-web-security',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--single-process',
'--user-data-dir="/tmp/chromium"'
]
Puppeteer is expecting Chromium version 901912, which seems to be version 93.0.4577.0. Might that be why it's not working?
I'm trying this with
[email protected]
on Lambda and I'm seeing this error when attempting to launch the browser:Error: Protocol error (Target.setDiscoverTargets): Target closed. at /opt/nodejs/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:71:63 at new Promise (<anonymous>) at Connection.send (/opt/nodejs/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:70:16) at Function.create (/opt/nodejs/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Browser.js:118:26) at ChromeLauncher.launch (/opt/nodejs/node_modules/puppeteer-core/lib/cjs/puppeteer/node/Launcher.js:109:56)
I'm also seeing this when re-attempting the launch:
ErrorEvent { target: WebSocket { _events: [Object: null prototype] { open: [Function], error: [Function] }, _eventsCount: 2, _maxListeners: undefined, _binaryType: 'nodebuffer', _closeCode: 1006, _closeFrameReceived: false, _closeFrameSent: false, _closeMessage: '', _closeTimer: null, _extensions: {}, _protocol: '', _readyState: 3, _receiver: null, _sender: null, _socket: null, _bufferedAmount: 0, _isServer: false, _redirects: 0, _url: 'ws://127.0.0.1:36089/devtools/browser/0fd89080-24a1-439e-955a-84de431d7f9e', _req: null, [Symbol(kCapture)]: false }, type: 'error', message: 'socket hang up', error: Error: socket hang up at connResetException (internal/errors.js:628:14) at Socket.socketOnEnd (_http_client.js:499:23) at Socket.emit (events.js:412:35) at Socket.emit (domain.js:470:12) at endReadableNT (internal/streams/readable.js:1317:12) at processTicksAndRejections (internal/process/task_queues.js:82:21) { code: 'ECONNRESET' } }
These are the arguments I'm using:
[ '--no-sandbox', '--no-zygote', '--disable-gpu', '--ignore-certificate-errors', '--allow-running-insecure-content', '--disable-web-security', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--single-process', '--user-data-dir="/tmp/chromium"' ]
Puppeteer is expecting Chromium version 901912, which seems to be version 93.0.4577.0. Might that be why it's not working?
I'll try building Chromium 901912. Please hang tight!
@AliasIO
I just compiled Chromium 93.0.4577.0 for ARM for you. It seems to work fine with Playwright, but I have no puppeteer instance to test with. Can you please check if it works?
The file can be downloaded here.
Let me know!
@lifesaverluke Thank you for that. Unfortunately I'm still getting the same 'socket hang up' error.
The closest I could find is these posts, although it's about AMD64:
https://github.com/puppeteer/puppeteer/issues/2430 https://stackoverflow.com/questions/59885937/chrome-aws-lambda-amazon-linux-2-getting-error-socket-hang-up
@AliasIO Are you sure you have the environment variable set?

Otherwise, can you please share your code, and Puppeteer version so that I can try to reproduce it?
@lifesaverluke I missed that! With the environment variable it's working. Thank you. 👍
@lifesaverluke – The link to the zip file you posted seems to have expired. Mind posting again? Exactly what I need. Thanks.
@lifesaverluke You are asking to pay $99/month to access your precompiled chromium binaries, am I reading you correctly?
I believe this is a feature request to add ARM64 binaries to chrome-aws-lambda, not a topic for promoting your stuff.
any updates?
any update on this?
Are there are noticeable performance improvements using ARM for this?
Hi everyone,
Currently there is no official port of Chromium to Amazon Linux 2 for the arm64 architecture used by AWS Lambda.
However, all is not lost! Since we can run container images on Lambda, we can build a lightweight container image based on Fedora 35 that includes a recent Chromium package and run it there. Here's an example Dockerfile you can use:
# Our code will live in the /function directory.
ARG FUNCTION_DIR="/function"
# Phase 1: Install Node, the Lambda runtime interface client (ric) bindings for
# Node, and the function code into a build container. This involves installing
# some build tools that we don't need in the final deployed image.
FROM public.ecr.aws/docker/library/fedora:35 AS build
ARG FUNCTION_DIR
RUN dnf install -y --setopt=install_weak_deps=False nodejs npm cmake autoconf automake libtool g++
RUN mkdir -p ${FUNCTION_DIR}
WORKDIR ${FUNCTION_DIR}
# Install node packages.
COPY package.json package-lock.json ${FUNCTION_DIR}/
RUN npm install
# If you prefer, you can comment out the below line, and place aws-lambda-ric
# into your package.json file instead.
RUN npm install aws-lambda-ric
# Install our function code.
COPY index.js ${FUNCTION_DIR}/
# Step 2: Build the deployment container image. We install only Node and
# Chromium, then copy in our function and its dependencies from the build image.
FROM public.ecr.aws/docker/library/fedora:35
ARG FUNCTION_DIR
RUN dnf -y --setopt=install_weak_deps=False install npm https://kojipkgs.fedoraproject.org//packages/chromium/93.0.4577.63/1.fc35/$(uname -m)/chromium-headless-93.0.4577.63-1.fc35.$(uname -m).rpm && \
dnf clean all && \
rm -rf /var/cache/yum
COPY --from=build ${FUNCTION_DIR} ${FUNCTION_DIR}
USER nobody
WORKDIR ${FUNCTION_DIR}
ENTRYPOINT ["/usr/bin/npx", "aws-lambda-ric"]
CMD ["index.handler"]
You'll only need to make one minor change in the chrome.puppeteer.launch()
invocation - specifically executablePath
:
browser = await chromium.puppeteer.launch({
args: chromium.args,
defaultViewport: chromium.defaultViewport,
headless: true,
ignoreHTTPSErrors: true,
executablePath: '/usr/lib64/chromium-browser/headless_shell',
});
📣 📈 I'm looking for data from customers as to whether there are any observable performance improvements or degradations when migrating from x86 to arm64 for their Lambda functions using Chromium headless. If you have useful data to report, please add it here!