Use GPU acceleration on Puppeteer

I’d like to run puppeteer with gpu acceleration for a webgl rendering system.

I’ve tried a few configurations but nothing seems to work.

Doing some research on this topic and it looks like it’s not an easy task.

So far, I’ve tried with this dockerfile, which I know, it’s absolutely not optimized. It’s a dev purpose for now.

I’ve used the ubuntu:22.04 image as mentionned in the documentation.

The following instruction keeps failing, it’s why it’s a comment.

RUN nvidia-smi

FROM ubuntu:22.04 AS base
RUN apt update -q && apt install -y ca-certificates wget && \
    wget -qO /cuda-keyring.deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb && \
    dpkg -i /cuda-keyring.deb && apt update -q

FROM base AS builder
RUN apt install -y --no-install-recommends git cuda-nvcc-12-2
RUN git clone --depth=1 https://github.com/nvidia/cuda-samples.git /cuda-samples
RUN cd /cuda-samples/Samples/1_Utilities/deviceQuery && \
    make && install -m 755 deviceQuery /usr/local/bin

FROM base AS runtime
RUN apt install -y --no-install-recommends libcudnn8 libcublas-12-2

RUN apt-get update && apt-get install -y \
    wget \
    ca-certificates \
    python3-pip \
    python3-venv \
    ffmpeg \
    libglib2.0-0 \
    libnss3 \
    libgconf-2-4 \
    libfontconfig1 \
    libxss1 \
    libxrandr2 \
    libasound2 \
    libatk1.0-0 \
    libatk-bridge2.0-0 \
    libgtk-3-0 \
    gnupg

RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
    sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list'

RUN apt-get update && apt-get install -y google-chrome-stable

#RUN nvidia-smi

COPY requirements.txt .
RUN python3 -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
RUN pip install --no-cache-dir -r requirements.txt

COPY . /app
WORKDIR /app
ENV PORT=8080

CMD ["python3", "main.py"]

I use google-chrome stable because I’ve readed it’s more likely to be compiled with gpu drivers or so.

Here’s my puppeteer flags:

        "--no-sandbox",
        "--enable-webgl",
        "--enable-gpu",
        "--enable-accelerated-2d-canvas",
        "--enable-gpu-rasterization",
        "--use-gl=desktop",
        "--use-vulkan",
        "--enable-zero-copy",
        "--enable-features=VaapiVideoDecoder,WebRTC-H264WithOpenH264FFmpeg,SharedArrayBuffer",
        "--ignore-gpu-blocklist",
        "--ozone-platform=headless",
        "--disable-dev-shm-usage",

and here’s my fly.toml:

app = 'drawnshow-renderer'
primary_region = 'ord'

[build]
  dockerfile = 'Dockerfile'

[env]
  PORT = '8080'
  PYTHONUNBUFFERED = '1'

[[services]]
  protocol = 'tcp'
  internal_port = 8080

  [[services.ports]]
    port = 80
    handlers = ['http']

  [[services.ports]]
    port = 443
    handlers = ['tls', 'http']

[[services]]
  protocol = 'udp'
  internal_port = 3478
  auto_start_machines = false
  ports = []

[[vm]]
  gpus = 1
  gpu_kind = 'a10'
  memory = '8gb'
  cpu_kind = 'performance'
  cpus = 4

[deploy]
  strategy = "immediate"
  max_unavailable = 0

If you could help me with this, I’ll be very happy to create a minimal repo to add in this list:

Hi… I’m definitely not one of the local GPU experts, but the builder itself doesn’t have a GPU—which is probably why the above line in the Dockerfile was failing.

The example in the official docs instead puts that in the entrypoint, meaning that it runs at every boot, on the actual target Machine.

echo "Inside entrypoint script."
chown $USERNAME:$USERNAME /home/$USERNAME
nvidia-smi # This seems to initialize the driver so that non-root user can use the GPU

Hope this helps move things forward a little!

As a side tip, unrelated to GPUs, try running fly config validate --strict whenever you encounter puzzling behavior on the Fly.io platform.

(flyctl doesn’t automatically complain about some syntactic and logical errors.)

1 Like

Thank for your help here.

Commenting a bit my dockerfile to ends with

ENTRYPOINT [“nvidia-smi”]

And I’ve got the table logged

After reading this post

I’ve edited the end of my dockerfile with

COPY entrypoint.sh /entrypoint.sh

RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

and in entrypoint.sh:

#!/bin/bash
set -e
nvidia-smi
exec python3 main.py

but currently, pupeeteer keeps using swiftshader, which is only CPU, not GPU accelerated.

It’s not entirely clear from your post if @mayailurus’ excellent advice has met with some success. In case it has not, can you explain why you need to run RUN nvidia-smi at build time?

Do you mean at runtime here? To fix this I would shell into the running machine and see if Puppeteer needs additional flags to use the GPU. Being in a shell will allow you to experiment interactively.

1 Like

So far, I don’t have successfully enabled hardware acceleration.

I have created a public document with all the combinations drivers/puppeeteer tested so far. I’ll start fill it in a few moments. Fly.io puppeeteer gpu accelerated combinations - Google Docs

I have found a blog post on the chromium project, mentionning it’s quite a hard task to do, flags can change from one chrome version to another.

Thanks for your advise on iterating interactively with ssh. This will help for sure

1 Like

I’ve done a lot of tests, looks like the gpu is not available for rendering, only for computing.

If there is a gpu expert, I’d like a confirmation or no about that

I’m not a GPU expert but to my understanding this is correct for some of our GPUs. try the L40s instead, those should have graphics accelerators as well as compute.

Thanks for this idea, but so far I have failed to use gpu acceleration
here is my last attempt

Dockerfile:

FROM ubuntu:22.04

# Installer les dépendances système (dont les bibliothèques GPU)
RUN apt-get update && \
    apt-get install -y wget gnupg2 python3 python3-pip \
    libnss3 libatk-bridge2.0-0 libgtk-3-0 \
    libx11-xcb1 libxcomposite1 libxdamage1 libxrandr2 libgbm1 libasound2 \
    --no-install-recommends && \
    apt-get clean

# Installer Chromium
RUN wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb && \
    apt-get install -y ./google-chrome-stable_current_amd64.deb && \
    rm google-chrome-stable_current_amd64.deb

# Installer pyppeteer
RUN pip3 install pyppeteer

# Ajouter un user non-root si besoin
RUN useradd -m appuser

# Dossier de travail
WORKDIR /home/appuser/app

COPY . .

COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

entrypoint.sh:

#!/bin/bash
set -e
nvidia-smi
sleep infinity

and after ssh connection:

google-chrome   --headless=new   --use-gl=gl-angle   --ignore-gpu-blocklist   --enable-gpu   --enable-webgl   --enable-accelerated-video-decode   --disable-software-rasterizer   --disable-dev-shm-usage   --no-sandbox   --disable-features=VizDisplayCompositor   --dump-dom https://webglreport.com

And the output:

[2196:2218:0726/200735.364406:ERROR:dbus/bus.cc:408] Failed to connect to the bus: Failed to connect to socket /run/dbus/system_bus_socket: No such file or directory
[2196:2221:0726/200735.366617:ERROR:dbus/bus.cc:408] Failed to connect to the bus: Failed to connect to socket /run/dbus/system_bus_socket: No such file or directory
[2196:2221:0726/200735.366662:ERROR:dbus/bus.cc:408] Failed to connect to the bus: Failed to connect to socket /run/dbus/system_bus_socket: No such file or directory
[2196:2218:0726/200735.370425:ERROR:dbus/bus.cc:408] Failed to connect to the bus: Could not parse server address: Unknown address type (examples of valid types are "tcp" and on UNIX "unix")
[2196:2218:0726/200735.370619:ERROR:dbus/bus.cc:408] Failed to connect to the bus: Could not parse server address: Unknown address type (examples of valid types are "tcp" and on UNIX "unix")
[2196:2218:0726/200735.370631:ERROR:dbus/bus.cc:408] Failed to connect to the bus: Could not parse server address: Unknown address type (examples of valid types are "tcp" and on UNIX "unix")
[2196:2218:0726/200735.370635:ERROR:dbus/bus.cc:408] Failed to connect to the bus: Could not parse server address: Unknown address type (examples of valid types are "tcp" and on UNIX "unix")
[2230:2230:0726/200735.376723:ERROR:ui/gl/init/gl_factory.cc:103] Requested GL implementation (gl=none,angle=none) not found in allowed implementations: [(gl=egl-angle,angle=default)].
[2230:2230:0726/200735.379664:ERROR:components/viz/service/main/viz_main_impl.cc:184] Exiting GPU process due to errors during initialization
[2196:2218:0726/200735.380476:ERROR:dbus/bus.cc:408] Failed to connect to the bus: Could not parse server address: Unknown address type (examples of valid types are "tcp" and on UNIX "unix")
[2196:2218:0726/200735.392718:ERROR:dbus/bus.cc:408] Failed to connect to the bus: Could not parse server address: Unknown address type (examples of valid types are "tcp" and on UNIX "unix")
[2196:2196:0726/200735.456627:ERROR:dbus/object_proxy.cc:590] Failed to call method: org.freedesktop.DBus.NameHasOwner: object_path= /org/freedesktop/DBus: unknown error type: 
[2196:2196:0726/200735.459360:ERROR:dbus/object_proxy.cc:590] Failed to call method: org.freedesktop.DBus.NameHasOwner: object_path= /org/freedesktop/DBus: unknown error type: 
[2196:2196:0726/200735.459648:ERROR:dbus/object_proxy.cc:590] Failed to call method: org.freedesktop.DBus.NameHasOwner: object_path= /org/freedesktop/DBus: unknown error type: 
[2196:2218:0726/200735.459708:ERROR:dbus/bus.cc:408] Failed to connect to the bus: Could not parse server address: Unknown address type (examples of valid types are "tcp" and on UNIX "unix")
[2196:2218:0726/200735.459717:ERROR:dbus/bus.cc:408] Failed to connect to the bus: Could not parse server address: Unknown address type (examples of valid types are "tcp" and on UNIX "unix")
[2267:2267:0726/200735.469487:ERROR:ui/gl/init/gl_factory.cc:103] Requested GL implementation (gl=none,angle=none) not found in allowed implementations: [(gl=egl-angle,angle=default)].
[2196:2279:0726/200735.471798:ERROR:dbus/bus.cc:408] Failed to connect to the bus: Failed to connect to socket /run/dbus/system_bus_socket: No such file or directory
[2196:2279:0726/200735.471844:ERROR:dbus/bus.cc:408] Failed to connect to the bus: Failed to connect to socket /run/dbus/system_bus_socket: No such file or directory
[2196:2279:0726/200735.471894:ERROR:dbus/bus.cc:408] Failed to connect to the bus: Failed to connect to socket /run/dbus/system_bus_socket: No such file or directory
[2196:2279:0726/200735.472042:ERROR:dbus/bus.cc:408] Failed to connect to the bus: Failed to connect to socket /run/dbus/system_bus_socket: No such file or directory
[2196:2279:0726/200735.473129:ERROR:dbus/bus.cc:408] Failed to connect to the bus: Failed to connect to socket /run/dbus/system_bus_socket: No such file or directory
[2267:2267:0726/200735.476016:ERROR:components/viz/service/main/viz_main_impl.cc:184] Exiting GPU process due to errors during initialization
[2196:2196:0726/200735.477442:ERROR:dbus/object_proxy.cc:590] Failed to call method: org.freedesktop.DBus.NameHasOwner: object_path= /org/freedesktop/DBus: unknown error type: 
[2196:2196:0726/200735.477567:ERROR:dbus/object_proxy.cc:590] Failed to call method: org.freedesktop.DBus.NameHasOwner: object_path= /org/freedesktop/DBus: unknown error type: 
[2295:2295:0726/200735.498611:ERROR:ui/gl/init/gl_factory.cc:103] Requested GL implementation (gl=none,angle=none) not found in allowed implementations: [(gl=egl-angle,angle=default)].
[2295:2295:0726/200735.502733:ERROR:components/viz/service/main/viz_main_impl.cc:184] Exiting GPU process due to errors during initialization
[2317:2317:0726/200735.526696:ERROR:ui/gl/init/gl_factory.cc:103] Requested GL implementation (gl=none,angle=none) not found in allowed implementations: [(gl=egl-angle,angle=default)].
[2317:2317:0726/200735.531669:ERROR:components/viz/service/main/viz_main_impl.cc:184] Exiting GPU process due to errors during initialization
[2329:2329:0726/200735.546599:ERROR:ui/gl/init/gl_factory.cc:103] Requested GL implementation (gl=none,angle=none) not found in allowed implementations: [(gl=egl-angle,angle=default)].
[2329:2329:0726/200735.549038:ERROR:components/viz/service/main/viz_main_impl.cc:184] Exiting GPU process due to errors during initialization

Does nvidia-smi have any options it can take, like --verbose? Chrome may be tricky because you presumably have to get the frame buffer to work with the GPU, but a Nvidia binary may be able to hook straight into a graphics-capable GPU (if only to show you the machine is capable).

I don’t know about nvidia-smi options, however I’ve tried the tree following:

  • glxinfo
  • eglinfo
  • vulkaninfo

(With additional packages installations)
Here’s the results with the l40s GPU:
-glxinfo:

Error: unable to open display

  • eglinfo:

EGL vendor string: Mesa Project

  • vulkaninfo:

Cannot create Vulkan instance.
This problem is often caused by a faulty installation of the Vulkan driver or attempting to use a GPU that does not support Vulkan.
ERROR at ./vulkaninfo/vulkaninfo.h:649:vkCreateInstance failed with ERROR_INCOMPATIBLE_DRIVER

Edit: it’s not clear but so far it’s only software acceleration for graphics, no gpu acceleration

1 Like

Update:

I made it works but with another cloud provider.

Here the step to reproduce on july 2025:

Create an account on imgbb.com and retrieve your api key (or adapt the end to upload the screenshot to your service)

Deploy an ubuntu worker + apt-get update + apt-get install -y wget curl + wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb && \
    apt-get install -y ./google-chrome-stable_current_amd64.deb && \
    rm google-chrome-stable_current_amd64.deb + google-chrome \
  --no-sandbox \
  --headless=new \
  --use-angle=vulkan \
  --enable-features=Vulkan \
  --disable-vulkan-surface \
  --enable-unsafe-webgpu \
  --disable-search-engine-choice-screen \
  --ash-no-nudges \
  --no-first-run \
  --disable-features=Translate \
  --no-default-browser-check \
  --window-size=1280,720 \
  --allow-chrome-scheme-url \
  --screenshot=/tmp/chrome_vulkan_test.png \
  https://webglreport.com/?v=2 + curl -F "key=$IMGBB_API_KEY" -F "image=@/tmp/chrome_vulkan_test.png" https://api.imgbb.com/1/upload

You should have an url to see the webglreport

here’s mine

google flags have been found here:

looks like it works better with ubuntu:24.04

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

Hello! I managed to make it work with L40S and A10 gpus.

The full app can be found at GitHub - fly-apps/headless-chrome-on-gpu: Example app of a headless chrome using Vulkan GPU rendering

and it is live (can’t say forever) at https://dan-webgl.fly.dev/

thanks!

2 Likes

Do you need to record a video from a WebGL sketch? Have you look at other options such as offline / off screen rendering of WebGL sketch?

If you just want to take a picture from a frame and you have written the code for your WebGL app you could potentially get away with just changing your sketch to render the only frame that you need, take the screenshot and exit and if my memory doesn’t trick me you could get away with that without GPU acceleration.

It might be be easier for us to help if you if you could explain what you’re trying to achieve as opposed to which technical problem you’re dealing with!

Good luck anyway!

Best Regards,

nu11soft

You nailed it, awesome !
I’ve been across your repo, the main difference I see are the env variables

“NVIDIA_VISIBLE_DEVICES” + “NVIDIA_DRIVER_CAPABILITIES” right ?

1 Like

Yes, I think that made a difference but also installing libvulkan1 vulkan-tools libdrm2 libgbm1 mesa-utils and running ldconfig in the entrypoint.

mesa-utils was the last bit, I think it pulls libegl lib and that is what is truly needed apart of libvulkan

1 Like