skip to Main Content

I’m unable to run my unit tests on Puppeteer inside of a Docker container. My host is a MacOS with Apple Silicon M1 (arm64) chip. I’ve also tried to follow the instructions from the Puppeteer Github documentation but they are meant for amd64 instead. Any suggestion?

3

Answers


  1. Chosen as BEST ANSWER

    Installing puppeteer NPM package directly won't work for some reason and sadly the official Puppeteer documentation in GitHub is not compatible with arm64 architecture.

    This is how I've prepared my Dockerfile:

    FROM node:16
    
    RUN apt-get update 
     && apt-get install -y chromium 
        fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 
        --no-install-recommends
        
    USER node # non-root user that comes with `node` images.
    
    WORKDIR /app
    
    COPY --chown=node package.json .
    COPY --chown=node package-lock.json .
    
    ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
    ENV PUPPETEER_EXECUTABLE_PATH /usr/bin/chromium
    
    RUN npm install
    
    COPY --chown=node . /app
    

    The Dockerfile as it is configured is native to Apple Silicon (linux/arm64) as well as native for amd64 (linux/amd64) architectures.

    You also must pass --no-sandbox argument to the browser on your code:

    export async function createBrowserInstance(): Promise<puppeteer.Browser> {
        return await puppeteer.launch({
            args: ['--no-sandbox'], // Required.
            headless: true,
        });
    }
    

    The extra flag disables the browser's dev sandboxing, so make sure to access only trusted pages. Otherwise it's fine. Please, somebody from the future, please feel free to edit this answer or comment how to get rid of the --no-sandbox argument.


  2. The only way I have been able to run Puppeteer via Docker on Apple Silicon is by.

    1. Creating the image by specifying amd64 platform
    FROM --platform=linux/amd64 node:18
    
    1. Enabling "Use Rosetta" support in Docker Desktop

    enter image description here

    1. Following the current Puppeteer Docker instructions to manually install Chromium instead of installing it as part of Puppeteer.

    Modified Puppeteer Docker File

    This example simplifies the current Puppeteer instructions. I removed their create user instructions because one is included in the node image. Also, they wipe out the apt registry after installing Chromium, preventing you from installing anything else. Add that back if you feel the need.

    
    FROM --platform=linux/amd64 node:18
    
    # We can define environment variables here
    # instead of specifying them when we launch Puppeteer. 
    # The path may change depending on your platform and installed binary.
    ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
    ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome-stable
    
    
    RUN apt-get update 
        && apt-get install -y wget gnupg 
        && wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | gpg --dearmor -o /usr/share/keyrings/googlechrome-linux-keyring.gpg 
        && sh -c 'echo "deb [arch=amd64 signed-by=/usr/share/keyrings/googlechrome-linux-keyring.gpg] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' 
        && apt-get update 
        && apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-khmeros fonts-kacst fonts-freefont-ttf libxss1 
          --no-install-recommends
    
    # If you desire to run in Chrome sandbox mode, change to a non-root user, and make sure you launch your image with `cap_add: SYS_ADMIN`.
    
    USER node
    

    Running As Non-Root With Chromium Sandbox Enabled

    1. Set a non-root user in your dockerfile
    2. Enable cap_add: SYS_ADMIN when launching your image.

    Example docker compose

    services: {
      node: {
        cap_add:
          - SYS_ADMIN
      }
    }
    

    With the environment variables set in DOCKERFILE, cap_add set, and a non-root user running, you can just fire up Puppeteer with it’s default paranoid sandboxing.

    In DOCKERFILE

    # Use the non-root user that comes with `node` image,
    # Or another if you wish.
    USER node
    

    In your Javascript

    const browser = await puppeteer.launch({
       headless: true
    })
    

    Running As Root And Bypassing Chromium Sandbox

    If you would rather rough it and disable Chromium Sandbox, just run as the default root user, and turn off the sandbox protection.

    1. Do not set a user in your dockerfile
    2. When launching Puppeteer, disable the sandbox
    const browser = await puppeteer.launch({
       args: [
         '--no-sandbox'
       ],
       headless: true
    })
    

    References:

    https://github.com/puppeteer/puppeteer/blob/main/docker/Dockerfile

    Login or Signup to reply.
  3. If you share your codebase with not ARM members, you could use if ARM then in your Dockerfile to be compatible with your colleagues.

    # ... common dockerfile commands shared for all architectures
    
    # Chromium fix for ARM (like Apple M1) 
    RUN if [ "$(uname -m)" = "aarch64" ] ; then 
            apt-get update && apt-get install -y chromium ; 
            export PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true ; 
            export PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser ; 
        fi
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search