Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Possible to run Headless Chrome/Chromium in a Google Cloud Function?

Is there any way to run Headless Chrome/Chromium in a Google Cloud Function? I understand I can include and run statically compiled binaries in GCF. Can I get a statically compiled version of Chrome that would work for this?

like image 891
at. Avatar asked May 02 '17 08:05

at.


People also ask

Is it possible to run Google Chrome in headless mode with extensions?

You can run Chrome with extensions headless using Xvfb. Use chrome-remote-interface (or another Chrome Debug Protocol client) to trigger the screenshot.

What is the difference between Chrome and headless Chrome?

Headless Chrome is a way to run the Chrome browser in a headless environment without the full browser UI. One of the benefits of using Headless Chrome (as opposed to testing directly in Node) is that your JavaScript tests will be executed in the same environment as users of your site.

What is headless Google Chrome?

Headless mode is a functionality that allows the execution of a full version of the latest Chrome browser while controlling it programmatically. It can be used on servers without dedicated graphics or display, meaning that it runs without its “head”, the Graphical User Interface (GUI).

How do I launch Chrome headless?

Which command starts the google chrome web browser in headless mode? As we have already seen, you just have to add the flag –headless when you launch the browser to be in headless mode. With CLI (Command Line Interface), just write: chrome \<br> – headless \ # Runs Chrome in headless mode.


2 Answers

The Node.js 8 runtime for Google Cloud Functions now includes all the necessary OS packages to run Headless Chrome.

Here is a code sample of an HTTP function that returns screenshots:

Main index.js file:

const puppeteer = require('puppeteer');

exports.screenshot = async (req, res) => {
  const url = req.query.url;

  if (!url) {
    return res.send('Please provide URL as GET parameter, for example: <a href="?url=https://example.com">?url=https://example.com</a>');
  }

  const browser = await puppeteer.launch({
    args: ['--no-sandbox']
  });
  const page = await browser.newPage();
  await page.goto(url);
  const imageBuffer = await page.screenshot();
  await browser.close();

  res.set('Content-Type', 'image/png');
  res.send(imageBuffer);
}

and package.json

{
  "name": "screenshot",
  "version": "0.0.1",
  "dependencies": {
    "puppeteer": "^1.6.2"
  }
}
like image 156
Steren Avatar answered Oct 13 '22 03:10

Steren


I've just deployed a GCF function running headless Chrome. A couple takeways:

  1. you have to statically compile Chromium and NSS on Debian 8
  2. you have to patch environment variables to point to NSS before launching Chromium
  3. performance is much worse than what you'd get on AWS Lambda (3+ seconds)

For 1, you should be able to find plenty of instructions online.

For 2, the code that I'm using is the following:

static executablePath() {
  let bin = path.join(__dirname, '..', 'bin', 'chromium');
  let nss = path.join(__dirname, '..', 'bin', 'nss', 'Linux3.16_x86_64_cc_glibc_PTH_64_OPT.OBJ');

  if (process.env.PATH === undefined) {
    process.env.PATH = path.join(nss, 'bin');
  } else if (process.env.PATH.indexOf(nss) === -1) {
    process.env.PATH = [path.join(nss, 'bin'), process.env.PATH].join(':');
  }

  if (process.env.LD_LIBRARY_PATH === undefined) {
    process.env.LD_LIBRARY_PATH = path.join(nss, 'lib');
  } else if (process.env.LD_LIBRARY_PATH.indexOf(nss) === -1) {
    process.env.LD_LIBRARY_PATH = [path.join(nss, 'lib'), process.env.LD_LIBRARY_PATH].join(':');
  }

  if (fs.existsSync('/tmp/chromium') === true) {
    return '/tmp/chromium';
  }

  return new Promise(
    (resolve, reject) => {
      try {
        fs.chmod(bin, '0755', () => {
          fs.symlinkSync(bin, '/tmp/chromium'); return resolve('/tmp/chromium');
        });
      } catch (error) {
        return reject(error);
      }
    }
  );
}

You also need to use a few required arguments when starting Chrome, namely:

--disable-dev-shm-usage
--disable-setuid-sandbox
--no-first-run
--no-sandbox
--no-zygote
--single-process

I hope this helps.

like image 5
Alix Axel Avatar answered Oct 13 '22 05:10

Alix Axel