Fix docker file
This commit is contained in:
84
Dockerfile
84
Dockerfile
@@ -1,40 +1,104 @@
|
||||
# Multi-stage Dockerfile.
|
||||
#
|
||||
# Why two stages
|
||||
# ──────────────
|
||||
# `canvas` is a native-binding npm package. It needs Cairo/Pango/etc.
|
||||
# at runtime, and python3+make+g++ at install-time to compile its
|
||||
# native bindings (no prebuilt binary covers the alpine musl+napi+linux
|
||||
# combination at this canvas version; prebuild-install falls back to
|
||||
# node-gyp, which needs the compile toolchain).
|
||||
#
|
||||
# The naive single-stage approach would either:
|
||||
# (a) keep python3+make+g++ in the final image — inflates the image
|
||||
# by ~200MB of build tools nothing uses at runtime, or
|
||||
# (b) try to install --omit=dev in a runtime-only image — fails
|
||||
# because canvas tries to compile and has no python (this was
|
||||
# the bug fixed in this revision).
|
||||
#
|
||||
# Two-stage solves both: install + compile + prune dev deps in the
|
||||
# builder (which has the toolchain), then COPY the resulting
|
||||
# node_modules into a slim runtime that only carries the C runtime
|
||||
# libs canvas needs at execution time.
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────
|
||||
# Stage 1: builder
|
||||
# Installs all deps (including dev), compiles native bindings,
|
||||
# builds the Vite bundle, then prunes dev deps so node_modules is
|
||||
# production-ready before we copy it.
|
||||
# ─────────────────────────────────────────────────────────────────
|
||||
FROM node:20-alpine AS builder
|
||||
|
||||
RUN apk add --no-cache cairo-dev pango-dev libjpeg-turbo-dev giflib-dev librsvg-dev pixman-dev python3 make g++
|
||||
# Native-binding build prerequisites:
|
||||
# • python3 / make / g++ — node-gyp toolchain for compiling canvas
|
||||
# • cairo-dev / pango-dev / etc. — headers canvas links against
|
||||
# These stay in the builder stage only; the runtime stage carries
|
||||
# the matching runtime libraries (no -dev suffix) without the
|
||||
# toolchain.
|
||||
RUN apk add --no-cache \
|
||||
cairo-dev pango-dev libjpeg-turbo-dev giflib-dev librsvg-dev pixman-dev \
|
||||
python3 make g++
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package manifests first so docker can cache the npm install
|
||||
# layer when only application source changes.
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
|
||||
COPY . .
|
||||
|
||||
# Pull Google Fonts into ./fonts/ so they end up in the runtime image. If the
|
||||
# build host has no network this step will produce missing-variant warnings;
|
||||
# the build still succeeds and the server falls back to system fonts.
|
||||
# Pull Google Fonts into ./fonts/ so they end up in the runtime image.
|
||||
# If the build host has no network this step will produce missing-variant
|
||||
# warnings; the build still succeeds and the server falls back to system
|
||||
# fonts.
|
||||
RUN npm run fetch-fonts || echo "Font fetch had warnings; continuing with whatever was downloaded."
|
||||
|
||||
RUN npm run build
|
||||
|
||||
# Drop dev dependencies (vitest, playwright, eslint, etc.) so the
|
||||
# node_modules we copy to runtime is production-only. This is the
|
||||
# step that was missing before — without it, the runtime stage had
|
||||
# to re-run `npm install` from scratch, which would re-trigger
|
||||
# canvas's native compile in an image that doesn't have the
|
||||
# toolchain. By pruning here, the runtime stage just copies the
|
||||
# already-compiled directory.
|
||||
RUN npm prune --production
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────
|
||||
# Stage 2: runtime
|
||||
# Carries only the runtime C libraries canvas links against plus
|
||||
# the fonts the export pipeline needs. node_modules is copied
|
||||
# whole from the builder; no `npm install` happens here.
|
||||
# ─────────────────────────────────────────────────────────────────
|
||||
FROM node:20-alpine
|
||||
|
||||
# Cairo + Pango are required by node-canvas at runtime.
|
||||
# The font packages cover the proprietary template families (Impact, Times,
|
||||
# Courier, Arial) via free equivalents that fontconfig will alias, plus emoji
|
||||
# rendering for sticker exports.
|
||||
# The font packages cover the proprietary template families (Impact,
|
||||
# Times, Courier, Arial) via free equivalents that fontconfig will
|
||||
# alias, plus emoji rendering for sticker exports.
|
||||
RUN apk add --no-cache \
|
||||
cairo pango libjpeg-turbo giflib librsvg pixman \
|
||||
ttf-liberation ttf-dejavu font-noto font-noto-emoji \
|
||||
fontconfig
|
||||
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm install --omit=dev
|
||||
|
||||
# Bring the production node_modules over from the builder rather
|
||||
# than installing fresh. This carries the already-compiled canvas
|
||||
# .node binary without needing python/make/g++ in this stage.
|
||||
COPY --from=builder /app/node_modules ./node_modules
|
||||
COPY --from=builder /app/package*.json ./
|
||||
|
||||
# Application files. server.js is the entry point; dist/ is the
|
||||
# Vite build output served as static; fonts/ is the result of
|
||||
# fetch-fonts above.
|
||||
COPY server.js ./
|
||||
COPY --from=builder /app/dist ./dist
|
||||
COPY --from=builder /app/fonts ./fonts
|
||||
RUN mkdir -p /app/uploads /app/exports
|
||||
|
||||
# Refresh fontconfig's cache so the newly-copied custom fonts are discoverable.
|
||||
# Refresh fontconfig's cache so the newly-copied custom fonts are
|
||||
# discoverable.
|
||||
RUN fc-cache -f /app/fonts || true
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||
|
||||
Reference in New Issue
Block a user