Azure-functions-host: Chrome headless doesn't work on Azure Functions on Linux

Created on 5 Sep 2019  路  22Comments  路  Source: Azure/azure-functions-host

Investigative information

Please provide the following:

  • Timestamp: 2019-09-04
  • Function App version (1.0 or 2.0): 2.0

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.

Most helpful comment

@anthonychu thank you for the update!!

All 22 comments

@ahmelsayed are you aware of any issues with this?

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?

sorry wrong button.

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.

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

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.

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

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

@ahmelsayed @Hazhzeng is this still an issue?

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?

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

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

Another example, microsoft.com/ja-jp

Before adding fonts:
image

After adding fonts:
image

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

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

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.

@anthonychu thank you for the update!!

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

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.

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

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

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

Was this page helpful?
0 / 5 - 0 ratings