Reputation: 6769
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?
Upvotes: 9
Views: 13548
Reputation: 301
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
Upvotes: 0
Reputation: 29099
The only way I have been able to run Puppeteer
via Docker
on Apple Silicon
is by.
amd64
platformFROM --platform=linux/amd64 node:18
Puppeteer
Docker
instructions to manually install Chromium
instead of installing it as part of Puppeteer.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
dockerfile
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
})
If you would rather rough it and disable Chromium Sandbox, just run as the default root
user, and turn off the sandbox protection.
dockerfile
const browser = await puppeteer.launch({
args: [
'--no-sandbox'
],
headless: true
})
References:
https://github.com/puppeteer/puppeteer/blob/main/docker/Dockerfile
Upvotes: 7
Reputation: 6769
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.
Upvotes: 18