Running the engine in a dockerised puppeteer

Hi everyone,

We are trying to automate screenshot capture from our application that babylon.js to generate preview thumbnail on our website.
To do that I create a node script that use headless Chrome with puppeteer and a dedicated version of our application that prepare the scene and send the screenshot back to puppeteer.

The bug

When I execute this script on my host machine (with the google chrome of the local puppeteer) everything works fine. But when I try to encapsulate the node automation script (and the puppeteer) into a docker container some of our mesh failed to load in the scene by triggering an error:

Error: Error: Unable to create texture
    at Engine._createTexture (http://host.docker.internal:3000/static/js/0.chunk.js:40623:13)
    at new InternalTexture (http://host.docker.internal:3000/static/js/0.chunk.js:74866:35)
    at Engine.createTexture (http://host.docker.internal:3000/static/js/0.chunk.js:40690:41)
    at new Texture (http://host.docker.internal:3000/static/js/0.chunk.js:77802:44)
    at http://host.docker.internal:3000/static/js/0.chunk.js:78199:21
    at Function.SerializationHelper.Parse (http://host.docker.internal:3000/static/js/0.chunk.js:122978:23)
    at Function.Texture.Parse [as _TextureParser] (http://host.docker.internal:3000/static/js/0.chunk.js:78154:88)
    at Function.SerializationHelper.Parse (http://host.docker.internal:3000/static/js/0.chunk.js:123008:52)
    at Function.PBRMaterial.Parse (http://host.docker.internal:3000/static/js/0.chunk.js:68782:89)
    at Function.Material.Parse (http://host.docker.internal:3000/static/js/0.chunk.js:83335:25)
    at parseMaterialById (http://host.docker.internal:3000/static/js/0.chunk.js:61549:75)
    at Object.importMesh (http://host.docker.internal:3000/static/js/0.chunk.js:62029:27)
    at http://host.docker.internal:3000/static/js/0.chunk.js:63003:27
    at dataCallback (http://host.docker.internal:3000/static/js/0.chunk.js:62746:7)
    at XMLHttpRequest.onReadyStateChange (http://host.docker.internal:3000/static/js/0.chunk.js:130078:15)
    at XMLHttpRequest.sentryWrapped (http://host.docker.internal:3000/static/js/3.chunk.js:1223:17)
    at Page._handleException (/app/node_modules/puppeteer/lib/Page.js:411:38)
    at CDPSession.Page.client.on.exception (/app/node_modules/puppeteer/lib/Page.js:102:60)
    at emitOne (events.js:116:13)
    at CDPSession.emit (events.js:211:7)
    at CDPSession._onMessage (/app/node_modules/puppeteer/lib/Connection.js:219:12)
    at Connection._onMessage (/app/node_modules/puppeteer/lib/Connection.js:119:19)
    at emitOne (events.js:116:13)
    at WebSocket.emit (events.js:211:7)
    at Receiver._receiver.onmessage (/app/node_modules/ws/lib/WebSocket.js:141:47)
    at Receiver.dataMessage (/app/node_modules/ws/lib/Receiver.js:389:14)

The mesh that trigger the error does not seems different from our others meshes.

My investigation

I have done some analysis of the WebGL capabilities of both context (in and out the container) to try to explain what append:

For what I understand:

  • the containerized Chrome have less resources allocated to compute the render,
  • some WebGL extension are missing in the containerized Chrome,
  • the containerized Chrome use Shiftshader to compensate the lack of GPU

Is this kind of error could be triggered by a lack of computation resource?

Other informations

Here my puppeteer configuration:

{
  "headless": false, // I activate the headless mode with the arg `--headless`
  "ignoreDefaultArgs": true,
  "args": [
    "--disable-background-networking",
    "--disable-background-timer-throttling",
    "--disable-client-side-phishing-detection",
    "--disable-default-apps",
    "--disable-dev-shm-usage",
    "--disable-extensions",
    "--disable-hang-monitor",
    "--disable-popup-blocking",
    "--disable-prompt-on-repost",
    "--disable-sync",
    "--disable-translate",
    "--metrics-recording-only",
    "--no-first-run",
    "--safebrowsing-disable-auto-update",
    "--enable-automation",
    "--password-store=basic",
    "--use-mock-keychain",

    "--headless",
    "--hide-scrollbars",
    "--mute-audio",

    "--no-sandbox",
    "--disable-setuid-sandbox",
    "--enable-logging",
    "--v=1",

    "--enable-webgl"
  ]
}

The question

I’m kind of stuck here, the generated error is not really detailed and I’ve in fact no good lead to continue my investigation. Is someone have lead? an idea? or an advise to work with WebGL in a docker container?

Thanks all for your help

You could rely on Xvfb instead as we do in our visual tests : http://elementalselenium.com/tips/38-headless

Then you could use a normal version of chromium vs the headless one to workaround the issue. I had better success with Xvfb than swiftshader and it looked like it supports WebGL2 depending on the virtual host.

BR,

As @sebavan indicates, I’m not certain how this might work in a headless version of Chromium. I’ve had issues in the past with versions of Chromium and Electron, and moving to a normal version showed none of these issues.

I don’t know if this helps, but I don’t see why your code shouldn’t work.

Galen

Thanks for your feedback. I will give a try to Xvfb and see if this works better in my case

1 Like

Good news using Xvfb resolve my issue! :tada:

Here my resulting image dockerfile docker-screenshot/Dockerfile at master · magelanLab/docker-screenshot · GitHub

It prepare a container with a Google Chrome installed, and configure a virtual screen

I do not advise you to use this container, it’s specific to our workflow but you could use it as inspiration

2 Likes