fix chrome install on docker

use --no-sandbox for google chrome
This commit is contained in:
hzrd149 2024-10-04 11:46:17 -05:00
parent f25e2409e9
commit 20de824ce8
8 changed files with 75 additions and 27 deletions

View File

@ -16,3 +16,7 @@ MAX_FILE_SIZE='2 MB'
# the hostname or ip of the upstream nginx proxy cache # the hostname or ip of the upstream nginx proxy cache
NGINX_CACHE_DIR='/var/nginx/cache' NGINX_CACHE_DIR='/var/nginx/cache'
# screenshots require Puppeteer to be setup https://pptr.dev/troubleshooting#setting-up-chrome-linux-sandbox
ENABLE_SCREENSHOTS="false"
SCREENSHOTS_IDR="./screenshots"

View File

@ -1,13 +1,38 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
FROM node:20-alpine AS base FROM node:20-slim AS base
ENV PNPM_HOME="/pnpm" ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH" ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable RUN corepack enable
RUN apk update && apk add --no-cache nginx supervisor # Setup nsite user
RUN groupadd -r nsite && useradd -r -g nsite -G audio,video nsite && usermod -d /app nsite
# Install nginx and supervisor
RUN apt-get update && apt-get install -y nginx supervisor
# setup supervisor
COPY supervisord.conf /etc/supervisord.conf COPY supervisord.conf /etc/supervisord.conf
# Setup nginx
COPY nginx/nginx.conf /etc/nginx/nginx.conf
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
RUN chown nsite:nsite -R /etc/nginx
# install google chrome for screenshots. copied from (https://pptr.dev/troubleshooting#running-puppeteer-in-docker)
# Install latest chrome dev package and fonts to support major charsets (Chinese, Japanese, Arabic, Hebrew, Thai and a few others)
# Note: this installs the necessary libs to make the bundled version of Chrome for Testing that Puppeteer
# installs, work.
RUN apt-get update \
&& apt-get install -y wget gnupg \
&& 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.list' \
&& apt-get update \
&& apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 \
--no-install-recommends \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app WORKDIR /app
COPY package.json . COPY package.json .
COPY pnpm-lock.yaml . COPY pnpm-lock.yaml .
@ -23,14 +48,6 @@ RUN pnpm build
FROM base AS main FROM base AS main
# Setup user
RUN addgroup -S nsite && adduser -S nsite -G nsite
RUN chown -R nsite:nsite /app
# Setup nginx
COPY nginx/nginx.conf /etc/nginx/nginx.conf
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
# setup nsite # setup nsite
COPY --from=prod-deps /app/node_modules /app/node_modules COPY --from=prod-deps /app/node_modules /app/node_modules
COPY --from=build ./app/build ./build COPY --from=build ./app/build ./build
@ -44,10 +61,16 @@ VOLUME [ "/screenshots" ]
EXPOSE 80 3000 EXPOSE 80 3000
ENV NSITE_PORT="3000" ENV NSITE_PORT="3000"
ENV NGINX_CACHE_DIR="/var/cache/nginx" ENV NGINX_CACHE_DIR="/var/cache/nginx"
ENV ENABLE_SCREENSHOTS="true"
ENV SCREENSHOTS_DIR="/screenshots" ENV SCREENSHOTS_DIR="/screenshots"
ENV PUPPETEER_SKIP_DOWNLOAD="true"
COPY docker-entrypoint.sh / COPY docker-entrypoint.sh /
RUN chmod +x /docker-entrypoint.sh RUN chmod +x /docker-entrypoint.sh
ENTRYPOINT ["/docker-entrypoint.sh"]
# change ownership of app
RUN chown nsite:nsite -R /app
# Run /docker-entrypoint as root so supervisor can run
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"] CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]

View File

@ -1,5 +1,7 @@
#!/bin/sh #!/bin/sh
chown -R nginx:nginx /var/cache/nginx echo Changing permission on volumes
chown -R nsite:nsite /var/cache/nginx
chown -R nsite:nsite /screenshots
exec "$@" exec "$@"

View File

@ -1,4 +1,4 @@
user nginx; user nsite;
worker_processes auto; worker_processes auto;
error_log /dev/stderr notice; error_log /dev/stderr notice;

View File

@ -24,6 +24,7 @@ const NSITE_HOST = process.env.NSITE_HOST || "0.0.0.0";
const NSITE_PORT = process.env.NSITE_PORT ? parseInt(process.env.NSITE_PORT) : 3000; const NSITE_PORT = process.env.NSITE_PORT ? parseInt(process.env.NSITE_PORT) : 3000;
const HOST = `${NSITE_HOST}:${NSITE_PORT}`; const HOST = `${NSITE_HOST}:${NSITE_PORT}`;
const ENABLE_SCREENSHOTS = process.env.SCREENSHOTS_DIR !== "false";
const SCREENSHOTS_DIR = process.env.SCREENSHOTS_DIR || "./screenshots"; const SCREENSHOTS_DIR = process.env.SCREENSHOTS_DIR || "./screenshots";
export { export {
@ -39,5 +40,6 @@ export {
NSITE_HOST, NSITE_HOST,
NSITE_PORT, NSITE_PORT,
HOST, HOST,
ENABLE_SCREENSHOTS,
SCREENSHOTS_DIR, SCREENSHOTS_DIR,
}; };

View File

@ -13,7 +13,15 @@ import send from "koa-send";
import { resolveNpubFromHostname } from "./helpers/dns.js"; import { resolveNpubFromHostname } from "./helpers/dns.js";
import { getNsiteBlobs, parseNsiteEvent } from "./events.js"; import { getNsiteBlobs, parseNsiteEvent } from "./events.js";
import { downloadFile, getUserBlossomServers } from "./blossom.js"; import { downloadFile, getUserBlossomServers } from "./blossom.js";
import { BLOSSOM_SERVERS, HOST, NGINX_CACHE_DIR, NSITE_HOST, NSITE_PORT, SUBSCRIPTION_RELAYS } from "./env.js"; import {
BLOSSOM_SERVERS,
ENABLE_SCREENSHOTS,
HOST,
NGINX_CACHE_DIR,
NSITE_HOST,
NSITE_PORT,
SUBSCRIPTION_RELAYS,
} from "./env.js";
import { userDomains, userRelays, userServers } from "./cache.js"; import { userDomains, userRelays, userServers } from "./cache.js";
import { invalidatePubkeyPath } from "./nginx.js"; import { invalidatePubkeyPath } from "./nginx.js";
import pool, { getUserOutboxes, subscribeForEvents } from "./nostr.js"; import pool, { getUserOutboxes, subscribeForEvents } from "./nostr.js";
@ -151,7 +159,8 @@ try {
} }
// get screenshots for websites // get screenshots for websites
app.use(async (ctx, next) => { if (ENABLE_SCREENSHOTS) {
app.use(async (ctx, next) => {
if (ctx.method === "GET" && ctx.path.startsWith("/screenshot")) { if (ctx.method === "GET" && ctx.path.startsWith("/screenshot")) {
const [pubkey, etx] = basename(ctx.path).split("."); const [pubkey, etx] = basename(ctx.path).split(".");
@ -161,7 +170,8 @@ app.use(async (ctx, next) => {
await send(ctx, getScreenshotPath(pubkey)); await send(ctx, getScreenshotPath(pubkey));
} else throw Error("Missing pubkey"); } else throw Error("Missing pubkey");
} else return next(); } else return next();
}); });
}
app.listen({ host: NSITE_HOST, port: NSITE_PORT }, () => { app.listen({ host: NSITE_HOST, port: NSITE_PORT }, () => {
console.log("Started on port", HOST); console.log("Started on port", HOST);
@ -180,7 +190,7 @@ if (SUBSCRIPTION_RELAYS.length > 0) {
} }
// invalidate screenshot for nsite // invalidate screenshot for nsite
if (nsite.path === "/" || nsite.path === "/index.html") { if ((ENABLE_SCREENSHOTS && nsite.path === "/") || nsite.path === "/index.html") {
await removeScreenshot(nsite.pubkey); await removeScreenshot(nsite.pubkey);
} }
} }

View File

@ -1,5 +1,5 @@
import { nip19 } from "nostr-tools"; import { nip19 } from "nostr-tools";
import puppeteer from "puppeteer"; import puppeteer, { PuppeteerLaunchOptions } from "puppeteer";
import { join } from "path"; import { join } from "path";
import pfs from "fs/promises"; import pfs from "fs/promises";
@ -25,7 +25,12 @@ export async function hasScreenshot(pubkey: string) {
export async function takeScreenshot(pubkey: string) { export async function takeScreenshot(pubkey: string) {
console.log(`${pubkey}: Generating screenshot`); console.log(`${pubkey}: Generating screenshot`);
const browser = await puppeteer.launch(); const opts: PuppeteerLaunchOptions = {
args: ["--no-sandbox"],
};
if (process.env.PUPPETEER_SKIP_DOWNLOAD) opts.executablePath = "google-chrome-stable";
const browser = await puppeteer.launch(opts);
const page = await browser.newPage(); const page = await browser.newPage();
const url = new URL(`http://${nip19.npubEncode(pubkey)}.localhost:${NSITE_PORT}`); const url = new URL(`http://${nip19.npubEncode(pubkey)}.localhost:${NSITE_PORT}`);
await page.goto(url.toString()); await page.goto(url.toString());
@ -36,5 +41,6 @@ export async function takeScreenshot(pubkey: string) {
export async function removeScreenshot(pubkey: string) { export async function removeScreenshot(pubkey: string) {
try { try {
await pfs.rm(getScreenshotPath(pubkey)); await pfs.rm(getScreenshotPath(pubkey));
console.log(`${pubkey}: Removed screenshot`);
} catch (error) {} } catch (error) {}
} }

View File

@ -12,10 +12,11 @@ stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0 stderr_logfile_maxbytes=0
[program:nsite] [program:nsite]
user=nsite
group=nsite
command=node /app command=node /app
autostart=true autostart=true
autorestart=true autorestart=true
user=root
stdout_logfile=/dev/stdout stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0 stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr stderr_logfile=/dev/stderr