Stop shipping Firefox and WebKit this server never launches
Microsoft's own Playwright image carries all three engines at 3.5 GB; this server calls chromium.launch and nothing else, ever. Node's own slim base plus Chromium installed on its own comes to 1.84 GB - most of that is the OS libraries --with-deps pulls in for a sandboxed Chromium to run at all, not the browser binary itself. One mistake made and caught while building this: installing under HOME=/tmp/browser-home, which is gone the instant the container starts, because /tmp is mounted as tmpfs. Moved to PLAYWRIGHT_BROWSERS_PATH=/ms-playwright, outside it - which is also where Microsoft's own image keeps browsers, and for the same reason. Verified under the production security constraints, not assumed to still hold on a different base: seccomp profile, cap_drop ALL plus cap_add SYS_CHROOT, read-only root, tmpfs /tmp, chromiumSandbox: true. Chromium launched sandboxed and navigated a real page under all of them together. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
44ca1c5435
commit
b06c9df73c
|
|
@ -1,14 +1,35 @@
|
|||
FROM mcr.microsoft.com/playwright:v1.63.0-noble
|
||||
# A slim Node base plus Chromium alone, not Microsoft's own image: that one ships Chromium,
|
||||
# Firefox and WebKit together at 3.5 GB, when this server only ever launches Chromium
|
||||
# (browser-service.js calls chromium.launch, never firefox or webkit). Built and verified this way
|
||||
# comes to 1.84 GB - Chromium's own weight plus the OS libraries it needs, nothing else - and every
|
||||
# security constraint below (seccomp, cap_drop, the read-only root, chromiumSandbox: true) was
|
||||
# checked against this base before it replaced the old one, not assumed to still hold.
|
||||
FROM node:24-bookworm-slim
|
||||
|
||||
ENV NODE_ENV=production
|
||||
ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
|
||||
# Outside /tmp on purpose: the container mounts /tmp as tmpfs (see mcp-stack.compose.yml), so a
|
||||
# browser installed under HOME=/tmp/... at build time would be gone the instant the real container
|
||||
# started - a mistake made once while building this image, and the reason it is called out here.
|
||||
# /ms-playwright is where Microsoft's own image keeps browsers, for the identical reason.
|
||||
ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
|
||||
ENV HOME=/tmp/browser-home
|
||||
|
||||
WORKDIR /app
|
||||
COPY package.json package-lock.json ./
|
||||
RUN npm ci --omit=dev --ignore-scripts \
|
||||
&& npm cache clean --force \
|
||||
&& chown -R pwuser:pwuser /app
|
||||
&& npm cache clean --force
|
||||
|
||||
# --with-deps installs the apt packages Chromium needs to run headless and sandboxed - fonts,
|
||||
# libgtk, libnss and the rest - which is most of what this layer costs; the browser binaries
|
||||
# themselves are a few hundred MB. chromium.launch({ headless: true }) reaches for the headless
|
||||
# shell build Playwright ships alongside full Chromium, so both are needed, not just one.
|
||||
RUN npx --yes playwright@1.63.0 install --with-deps chromium \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
|
||||
&& chmod -R o+rX /ms-playwright
|
||||
|
||||
RUN groupadd -r pwuser && useradd -r -g pwuser -G audio,video pwuser \
|
||||
&& mkdir -p /tmp/browser-home && chown -R pwuser:pwuser /app
|
||||
COPY --chown=pwuser:pwuser src ./src
|
||||
|
||||
USER pwuser
|
||||
|
|
|
|||
Loading…
Reference in New Issue