Azure / azure-functions-host

The host/runtime that powers Azure Functions
https://functions.azure.com
MIT License
1.92k stars 442 forks source link

Chrome headless doesn't work on Azure Functions on Linux #4883

Open sarvaje opened 5 years ago

sarvaje commented 5 years ago

Investigative information

Please provide the following:

Repro steps

  1. Add this code to you function (in my case, type httpTrigger)
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({ path: 'example.png' });
await browser.close();

Expected behavior

It should works

Actual behavior

An exception is throw:

message: spawn EACCES
stack: Error: spawn EACCES
    at ChildProcess.spawn (internal/child_process.js:313:11)
    at Object.exports.spawn (child_process.js:508:9)
    at Launcher.launch (/home/site/wwwroot/node_modules/puppeteer/lib/Launcher.js:133:40)
    at <anonymous>

Known workarounds

I don't know any.

Related information

According to this comment: https://github.com/Azure/azure-functions-host/issues/2417#issuecomment-366043565 It should work on linux, but we get the same error as in windows.

fabiocav commented 4 years ago

@ahmelsayed are you aware of any issues with this?

ahmelsayed commented 4 years ago

puppeteer seems to have a lot of dependencies that we don't include by default in our images.

apt-get install -y gconf-service libasound2 libatk1.0-0 libatk-bridge2.0-0 libc6 \
    libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 \
    libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 \
    libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 \
    libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation \
    libappindicator1 libnss3 lsb-release xdg-utils wget

Are you using Dedicated or Consumption Linux? Also how are you publishing?

ahmelsayed commented 4 years ago

sorry wrong button.

sarvaje commented 4 years ago

Are you using Dedicated or Consumption Linux? Also how are you publishing?

I tried in both. I was publishing using the VS Code extension. The only way to be able to use puppeteer is using a Docker image, but for that we can't use the Consumption plan.

puppeteer seems to have a lot of dependencies that we don't include by default in our images.

It is not only the dependencies, when I was testing this, the problem was that puppeteer needs to open a new process for the browser, and that is not allowed.

ahmelsayed commented 4 years ago

new process for the browser, and that is not allowed.

that should be an fine. My guess is that either a missing dependency is causing that or when the app was being packages, ./chrome file wasn't marked as executable x which might throw the access denied error. It works fine in dedicated with a custom docker image, so I think the only thing missing in consumption is the dependencies. Also puppeteer seems to require platform specific install, so you will need to npm install on a linux machine. We should enable uploading just package.json and doing npm install on the server side like we do with python /cc @Hazhzeng for FYI

verified on dedicated using: https://github.com/ahmelsayed/chrome-headless-func-test running: https://ahmels-linux-chrome.azurewebsites.net/api/HttpTrigger

sarvaje commented 4 years ago

We should enable uploading just package.json and doing npm install on the server side like we do with python

That would be nice, I remember I had to use wsl to upload the right version of some platform specific packages.

I think the only thing missing in consumption is the dependencies.

It would be nice to be able to run this in consumption mode.

@ahmelsayed @Hazhzeng If you need something on my side, please let me know.

benjamineberle commented 4 years ago

@sarvaje Did you find any solution to run puppeteer on serverless? Would like to do the same thing here. AWS seems to do better here...

hyperyn commented 4 years ago

Wondering if anyone's found a solution to this - our team's running into the same problem with missing dependencies on consumption Linux apps.

fabiocav commented 4 years ago

@ahmelsayed @Hazhzeng is this still an issue?

horihiro commented 4 years ago

Hello @fabiocav I confirmed that puppeteer works on Azure Functions on Linux thanks to the following PR for Node.js runtime https://github.com/Azure/azure-functions-docker/pull/225

But on some situation, Puppeteer, maybe playwright also, cannot render some characters in a web page because of lack of fonts.

For example, google.co.jp includes some Japanese characters, and the screenshot by puppeteer is following image. image Some characters were replaced to rectangles.

To resolve it, I found fonts should be added into /usr/share/fonts or /home/.fonts. as following repo. https://github.com/horihiro/azure-functions-puppeteer-node-cjkfont In the repo, at the begining of each function invocation, it is checked that the worker has the fonts in /home/.font

After adding the fonts, puppeteer can render them. image

But I think it is awkward solution... Do you have smarter solution to add fonts?

anthonychu commented 4 years ago

@horihiro Where does postinstall.sh install the fonts? (Is it /home/site/wwwroot/fonts or somewhere else?)

horihiro commented 4 years ago

In my approach, postinstall.sh downloads fonts into /home/site/wwwroot/fonts temporally during deployment. https://github.com/horihiro/azure-functions-puppeteer-node-cjkfont/blob/master/postinstall.sh#L5

And the fonts are copied to /home/.fonts at the beginning of each invocation if there is no fonts in /home/.fonts. (Edited: replace the process from copying to linking,) https://github.com/horihiro/azure-functions-puppeteer-node-cjkfont/blob/master/url2png/index.ts#L18

horihiro commented 4 years ago

Another example, microsoft.com/ja-jp

Before adding fonts: image

After adding fonts: image

anthonychu commented 4 years ago

@arjun27 Do you know if there's a way to add fonts without installing them to $HOME/.fonts? For example, can Playwright tell Chromium where to look for fonts? Hoping to allow customers to include fonts in their application package without the extra step that @horihiro is doing to copy them to $HOME/.fonts at run-time.

@ahmelsayed What are your thoughts on adding fonts?

anthonychu commented 4 years ago

@sarvaje @benjamineberle @hyperyn You can now run headless Chromium on Linux Consumption. Hope to have more official docs in the future but for now, check out this blog post for the steps to get it working.

ahmelsayed commented 4 years ago

We could add fonts as long as the license for them allows redistribution (which the ones in that repo seems to allow https://noto-website-2.storage.googleapis.com/pkgs/NotoSansCJKjp-hinted.zip) though I'm not sure I know what is the correct set of fonts to add.

sarvaje commented 4 years ago

@anthonychu thank you for the update!!

anthonychu commented 4 years ago

@ahmelsayed Yeah I'm not sure how to determine what fonts to add. Looking at the file sizes here, could have significant impact on image size as well.

horihiro commented 4 years ago

It seems to be difficult to determine which fonts are added.

If the function host had an initializing process for Node.js worker as discussing in https://github.com/Azure/azure-functions-host/issues/586 , customers can add any fonts which the customers want to add them in the process and the container image does not need to contain the fonts.

johnayoub commented 3 years ago

@anthonychu I was able to get puppeteer to work with the help for your blog post. However, I have been trying to deploy and use the run from package option with the all the dependencies bundled in but that is not working. Is that a current limitation? Any ideas?

anomepani commented 3 years ago

@anthonychu Does Chrome headless with puppeteersharp supported in Azure Function with C#?

anthonychu commented 3 years ago

@johnayoub Sorry I missed this. Are you still stuck? If you're using run from zip, you may have to set WEBSITE_MOUNT_ENABLED to true in app settings. Run from zip might not keep the execute bit on your files without this setting.

@anomepani Please take a look at this blog post for a sample. I haven't figured out how to download Chromium during the build, but you can download it when the function app instance starts up. Not great but it should work.

oneillci commented 2 years ago

Are there plans for this to also work on Windows plans?

Having something that can work on one runtime but not another, on one plan type but not another, even though it works in the local development environment really negates the "serverless" part of functions - ideally this should all be abstracted away and not a developers concern

silverl commented 1 year ago

Has something changed here? I've got an Az Function that's died twice today because of missing dependencies for running puppeteer chrome headless.

An error occurred attempting to create delivery receipt PDF: correlation ID 527891. Error Failed to launch browser! /tmp/Linux-848005/chrome-linux/chrome: error while loading shared libraries: libgobject-2.0.so.0: cannot open shared object file: No such file or directory

We're temporarily fixing it by using SSH to install the dependencies manually until we can find a resilient solution.

apt install libglib2.0-0 libnss3 libatk1.0-0 libatk-bridge2.0-0 libgbm1 libasound2 libgtk-3-0 libxshmfence1 libcups2 libpangocairo-1.0-0 libxss1 libx11-xcb1 fonts-liberation libappindicator3-1 libgcc1 libnspr4 lsb-release xdg-utils -y

Every time the function environment resets for whatever reason, it breaks.

georgeOsdDev commented 1 year ago

Let me share alternative solution about missing fonts.

default font config(/etc/fonts/fonts.conf) have below seting

<dir prefix="xdg">fonts</dir>

Thus if I set app settings XDG_DATA_HOME as /home/site/wwwroot/, fonts files in /home/site/wwwroot/fonts will be loaded.

I could install fonts via postinstall hook like below

#!/bin/bash
curl -L 'https://fonts.google.com/download?family=Noto%20Sans%20JP' -o font.zip
unzip font.zip -d ./fonts
rm -rf font.zip

I have a feature request to the platform side. If platform side change/etc/fonts/fonts.conf or /etc/fonts/conf.d to load fonts from /home/site/wwwroot/fonts by default, we did not use XDG_DATA_HOME appsettings. And this solution does not effect image size, it work as BYOF(bring your own fonts).

nippoolg commented 1 year ago

Has something changed here? I've got an Az Function that's died twice today because of missing dependencies for running puppeteer chrome headless.

An error occurred attempting to create delivery receipt PDF: correlation ID 527891. Error Failed to launch browser! /tmp/Linux-848005/chrome-linux/chrome: error while loading shared libraries: libgobject-2.0.so.0: cannot open shared object file: No such file or directory

We're temporarily fixing it by using SSH to install the dependencies manually until we can find a resilient solution.

apt install libglib2.0-0 libnss3 libatk1.0-0 libatk-bridge2.0-0 libgbm1 libasound2 libgtk-3-0 libxshmfence1 libcups2 libpangocairo-1.0-0 libxss1 libx11-xcb1 fonts-liberation libappindicator3-1 libgcc1 libnspr4 lsb-release xdg-utils -y

Every time the function environment resets for whatever reason, it breaks.

Did you solve the problem? Having the same after switching to Function Runtime 4.

silverl commented 1 year ago

@nippoolg No, we didn't solve the problem. We chose to move our service to a custom-built docker container so we could manage dependencies. I don't think it's safe to rely on Microsoft's choice of dependencies. They can change it at any time, as we've seen.

yuna-s commented 1 year ago

@anthonychu hi is there any plan to support Puppeteer and Playwright in Premium and Dedicated Plan for Azure Functions(Linux)?

ZaikinaEvgeniya-2 commented 4 months ago

any solution?