chrome-aws-lambda icon indicating copy to clipboard operation
chrome-aws-lambda copied to clipboard

[REQUEST] Include ARM_64 binaries

Open villetuomaala opened this issue 3 years ago • 17 comments

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?

villetuomaala avatar Sep 30 '21 09:09 villetuomaala

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.

lifesaverluke avatar Oct 25 '21 07:10 lifesaverluke

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?

villetuomaala avatar Oct 27 '21 11:10 villetuomaala

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.

lifesaverluke avatar Oct 27 '21 11:10 lifesaverluke

@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!

lifesaverluke avatar Oct 27 '21 14:10 lifesaverluke

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?

AliasIO avatar Oct 27 '21 23:10 AliasIO

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!

lifesaverluke avatar Oct 28 '21 11:10 lifesaverluke

@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 avatar Oct 29 '21 14:10 lifesaverluke

@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 avatar Oct 29 '21 21:10 AliasIO

@AliasIO Are you sure you have the environment variable set?

envvars

Otherwise, can you please share your code, and Puppeteer version so that I can try to reproduce it?

lifesaverluke avatar Oct 30 '21 11:10 lifesaverluke

@lifesaverluke I missed that! With the environment variable it's working. Thank you. 👍

AliasIO avatar Oct 30 '21 20:10 AliasIO

@lifesaverluke – The link to the zip file you posted seems to have expired. Mind posting again? Exactly what I need. Thanks.

mohamedattahri avatar Nov 04 '21 02:11 mohamedattahri

@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.

anking avatar Nov 05 '21 17:11 anking

any updates?

morgothulhu avatar Dec 10 '21 17:12 morgothulhu

any update on this?

e-moshaya avatar Dec 27 '21 01:12 e-moshaya

Are there are noticeable performance improvements using ARM for this?

jpike88 avatar Jan 10 '22 14:01 jpike88

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!

otterley avatar Feb 02 '22 00:02 otterley