Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

Issue on Cloud Run container with Chrome, Node and CDP (chrome-remote-interface) ECONNREFUSED

I have created a debian container image with node, npm and 

google-chrome-stable installed via apt-get. 
(Note that for my purposes, I need Chrome, as Chromium will not suffice.)
 
The container runs a node script that uses chrome-launcher and chrome-remote-interface to create a CDP session and attach to the Network Request handler to sniff the network traffic.
 
Dockerfile (edited for brevity):
FROM debian:bullseye-slim
RUN apt-get update --fix-missing
RUN apt-get install -y ... [edited: installs curl, node, npm, and various libs and utils}

RUN curl -sSL https://dl.google.com/linux/linux_signing_key.pub | apt-key add -
RUN echo "deb [arch=amd64] https://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google.list
RUN apt-get update
RUN apt-get install -y google-chrome-stable --no-install-recommends
 
WORKDIR /usr/src
COPY package*.json ./
RUN npm install
COPY index.js ./
CMD [ "node", "index.js" ]
 
index.js (also edited for brevity):
import CDP from 'chrome-remote-interface';
import chromeLauncher from 'chrome-launcher';
 
const chromePort = 9222
const chromeFlags = ['--no-first-run', '--no-default-browser-check', '--disable-fre', '--disable-translate', '--disable-extensions', '--remote-debugging-address=127.0.0.1', `--remote-debugging-port=${chromePort}`];
const chromeUrl = 'https://www.google.com'; // Edited; example URL
 
const main = async () => {
  let chrome;
  try {
    // Launch the Chrome application
    chrome = await chromeLauncher.launch({ port: chromePort, chromeFlags });
    console.log(`Chrome launched with debugging port on ${chrome.port}`);

    // Create a CDP session for the browser window
    const browserCDP = await connectCDP(null);

// Navigate to the site
    await browserCDP.Page.navigate({ url: chromeUrl });

    // Shutdown CDP session
    await browserCDP.close(); 
  } finally {
// Close the Chrome application
    if (chrome) {
      await chrome.kill();
    }
  }
}
 
async function connectCDP(target) {
  // Connect chrome remote interface
  const cdp = await CDP({ port: chromePort, target });

  // Define network interception handler
  cdp.Network.requestIntercepted(async ({ interceptionId, request}) => {

    ... [ edited for brevity ] ...

    // Allow request to continue
    try {
      cdp.Network.continueInterceptedRequest({ interceptionId });
    } catch (e) {
      console.log(e);
    }
  });

  // Enable network interception
  await cdp.Network.setRequestInterception({ patterns: [{ urlPattern: '*', interceptionStage: 'HeadersReceived' }] });

  // Return the CDP instance
  return cdp;
}

// Run
main().catch(err => {
console.error(err);
});
 

 

I have tested this image locally (although with Docker not gVisor), and everything works as expected. When using docker run -it -e DISPLAY=host.docker.internal:0 I can even see the browser window in XQuartz.
However when I deploy to Cloud Run as a job, it throws an error connecting to Chrome via CDP. 
 
Error: connect ECONNREFUSED 127.0.0.1:9222 
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1138:16)
 
I have tried:
-  Adding EXPOSE 9222 to the Dockerfile with no change in error message.
-  Installing ufw to ufw allow 9222 (but could not get around the need to sudo)
-  With and without the --no-sandbox flag with no change in error message.
-  With the --headless flag I get a different error: 
TypeError: Cannot read property 'webSocketDebuggerUrl' of undefined 
at Chrome._fetchDebuggerURL (/usr/src/node_modules/chrome-remote-interface/lib/chrome.js:183:31)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async Chrome._start (/usr/src/node_modules/chrome-remote-interface/lib/chrome.js:140:25)
    (This error DOES occur locally as well when using the --headless flag, so I have not pursued it)
 
I appreciate any suggestions, Thanks.
 
 
0 0 626
0 REPLIES 0