Docker improvement and fix screenshots

. Dockerfile optimization (reorder)
. Docker: Add xvfb package
. Docker: Add entrypoint.sh
. Launch dbus at container start (entrypoint.sh)
. Lauch Xvfb at container start (entrypoint.sh)
. Above fix screenshot error on docker
. Add environment variables:
. . SCREEN_RESOLUTION: for Xvfb resolution
. . BROWSER_WIDTH: for screenshot
. . BROWSER_HEIGHT: for screenshot
. . BROWSER_TIMEOUT: for screenshot
This commit is contained in:
Alexandre Galtier 2024-09-16 22:01:44 +02:00
parent 7ca22daa9a
commit 36bccfa748
No known key found for this signature in database
GPG Key ID: 40E41A173EA67F53
3 changed files with 42 additions and 15 deletions

View File

@ -1,3 +1,6 @@
###########################
#### APP Build #####
###########################
# Specify the Node.js version to use # Specify the Node.js version to use
ARG NODE_VERSION=21 ARG NODE_VERSION=21
@ -11,13 +14,12 @@ FROM node:${NODE_VERSION}-${DEBIAN_VERSION} AS build
SHELL ["/bin/bash", "-euo", "pipefail", "-c"] SHELL ["/bin/bash", "-euo", "pipefail", "-c"]
# Install Chromium browser and Download and verify Google Chromes signing key # Install Chromium browser and Download and verify Google Chromes signing key
RUN apt-get update -qq --fix-missing && \ RUN apt-get update --quiet --yes --fix-missing && \
apt-get -qqy install --allow-unauthenticated gnupg wget && \ DEBIAN_FRONTEND=noninteractive apt-get --quiet --yes install --allow-unauthenticated gnupg wget && \
wget --quiet --output-document=- https://dl-ssl.google.com/linux/linux_signing_key.pub | gpg --dearmor > /etc/apt/trusted.gpg.d/google-archive.gpg && \ wget --quiet --output-document=- https://dl-ssl.google.com/linux/linux_signing_key.pub | gpg --dearmor > /etc/apt/trusted.gpg.d/google-archive.gpg && \
echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google.list && \ echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google.list && \
apt-get update -qq && \ apt-get update --quiet --yes && \
apt-get -qqy --no-install-recommends install chromium traceroute python make g++ && \ DEBIAN_FRONTEND=noninteractive apt-get --quiet --yes --no-install-recommends install chromium traceroute python make g++
rm -rf /var/lib/apt/lists/*
# Run the Chromium browser's version command and redirect its output to the /etc/chromium-version file # Run the Chromium browser's version command and redirect its output to the /etc/chromium-version file
RUN /usr/bin/chromium --no-sandbox --version > /etc/chromium-version RUN /usr/bin/chromium --no-sandbox --version > /etc/chromium-version
@ -29,8 +31,10 @@ WORKDIR /app
COPY package.json yarn.lock ./ COPY package.json yarn.lock ./
# Run yarn install to install dependencies and clear yarn cache # Run yarn install to install dependencies and clear yarn cache
RUN apt-get update && \ RUN yarn install --frozen-lockfile --network-timeout 100000
yarn install --frozen-lockfile --network-timeout 100000 && \
# Cleanup
RUN rm -rf /var/lib/apt/lists/* && \
rm -rf /app/node_modules/.cache rm -rf /app/node_modules/.cache
# Copy all files to working directory # Copy all files to working directory
@ -39,24 +43,31 @@ COPY . .
# Run yarn build to build the application # Run yarn build to build the application
RUN yarn build --production RUN yarn build --production
# Final stage
###########################
#### Final STAGE #####
###########################
FROM node:${NODE_VERSION}-${DEBIAN_VERSION} AS final FROM node:${NODE_VERSION}-${DEBIAN_VERSION} AS final
RUN apt-get update --yes && \
DEBIAN_FRONTEND=noninteractive apt-get install --yes --no-install-recommends chromium traceroute xvfb && \
chmod 755 /usr/bin/chromium && \
rm -rf /var/lib/apt/lists/* /app/node_modules/.cache
WORKDIR /app WORKDIR /app
COPY package.json yarn.lock ./ COPY package.json yarn.lock ./
COPY --from=build /app . COPY --from=build /app .
RUN apt-get update && \
apt-get install -y --no-install-recommends chromium traceroute && \
chmod 755 /usr/bin/chromium && \
rm -rf /var/lib/apt/lists/* /app/node_modules/.cache
# Exposed container port, the default is 3000, which can be modified through the environment variable PORT # Exposed container port, the default is 3000, which can be modified through the environment variable PORT
EXPOSE ${PORT:-3000} EXPOSE ${PORT:-3000}
# Set the environment variable CHROME_PATH to specify the path to the Chromium binaries # Set the environment variable CHROME_PATH to specify the path to the Chromium binaries
ENV CHROME_PATH='/usr/bin/chromium' ENV CHROME_PATH='/usr/bin/chromium'
# Entrypoint to lauchn
COPY --chmod=755 entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
# Define the command executed when the container starts and start the server.js of the Node.js application # Define the command executed when the container starts and start the server.js of the Node.js application
CMD ["yarn", "start"] CMD ["yarn", "start"]

View File

@ -20,9 +20,12 @@ const screenshotHandler = async (targetUrl) => {
let browser = null; let browser = null;
try { try {
const width = process.env.BROWSER_WIDTH ? parseInt(process.env.BROWSER_WIDTH, 10) : 800;
const height = process.env.BROWSER_HEIGHT ? parseInt(process.env.BROWSER_HEIGHT, 10) : 600;
browser = await puppeteer.launch({ browser = await puppeteer.launch({
args: [...chromium.args, '--no-sandbox'], // Add --no-sandbox flag args: [...chromium.args, '--no-sandbox'], // Add --no-sandbox flag
defaultViewport: { width: 800, height: 600 }, defaultViewport: { width, height },
executablePath: process.env.CHROME_PATH || await chromium.executablePath, executablePath: process.env.CHROME_PATH || await chromium.executablePath,
headless: chromium.headless, headless: chromium.headless,
ignoreHTTPSErrors: true, ignoreHTTPSErrors: true,
@ -32,7 +35,8 @@ const screenshotHandler = async (targetUrl) => {
let page = await browser.newPage(); let page = await browser.newPage();
await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: 'dark' }]); await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: 'dark' }]);
page.setDefaultNavigationTimeout(8000); const browserTimeout = process.env.BROWSER_TIMEOUT ? parseInt(process.env.BROWSER_TIMEOUT, 10) : 8000;
page.setDefaultNavigationTimeout(browserTimeout);
await page.goto(targetUrl, { waitUntil: 'domcontentloaded' }); await page.goto(targetUrl, { waitUntil: 'domcontentloaded' });
await page.evaluate(() => { await page.evaluate(() => {

12
entrypoint.sh Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
SCREEN_RESOLUTION="${SCREEN_RESOLUTION:-1280x1024x24}"
if [[ ! "${SCREEN_RESOLUTION}" =~ ^[0-9]+x[0-9]+x(8|16|24)$ ]]; then
echo "SCREEN_RESOLUTION must match screen resolution like '1280x1024x24'"
echo "last number (color) must be 8,16 or 24"
exit 1
fi
service dbus start
[[ -z "${DISPLAY}" ]] && export DISPLAY=":99"
Xvfb "${DISPLAY}" -screen 0 "${SCREEN_RESOLUTION}" &
exec "${@}"