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
|
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
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy package manifests first so docker can cache the npm install
|
||||||
|
# layer when only application source changes.
|
||||||
COPY package*.json ./
|
COPY package*.json ./
|
||||||
RUN npm install
|
RUN npm install
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Pull Google Fonts into ./fonts/ so they end up in the runtime image. If the
|
# Pull Google Fonts into ./fonts/ so they end up in the runtime image.
|
||||||
# build host has no network this step will produce missing-variant warnings;
|
# If the build host has no network this step will produce missing-variant
|
||||||
# the build still succeeds and the server falls back to system fonts.
|
# 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 fetch-fonts || echo "Font fetch had warnings; continuing with whatever was downloaded."
|
||||||
|
|
||||||
RUN npm run build
|
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
|
FROM node:20-alpine
|
||||||
|
|
||||||
# Cairo + Pango are required by node-canvas at runtime.
|
# Cairo + Pango are required by node-canvas at runtime.
|
||||||
# The font packages cover the proprietary template families (Impact, Times,
|
# The font packages cover the proprietary template families (Impact,
|
||||||
# Courier, Arial) via free equivalents that fontconfig will alias, plus emoji
|
# Times, Courier, Arial) via free equivalents that fontconfig will
|
||||||
# rendering for sticker exports.
|
# alias, plus emoji rendering for sticker exports.
|
||||||
RUN apk add --no-cache \
|
RUN apk add --no-cache \
|
||||||
cairo pango libjpeg-turbo giflib librsvg pixman \
|
cairo pango libjpeg-turbo giflib librsvg pixman \
|
||||||
ttf-liberation ttf-dejavu font-noto font-noto-emoji \
|
ttf-liberation ttf-dejavu font-noto font-noto-emoji \
|
||||||
fontconfig
|
fontconfig
|
||||||
|
|
||||||
WORKDIR /app
|
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 server.js ./
|
||||||
COPY --from=builder /app/dist ./dist
|
COPY --from=builder /app/dist ./dist
|
||||||
COPY --from=builder /app/fonts ./fonts
|
COPY --from=builder /app/fonts ./fonts
|
||||||
RUN mkdir -p /app/uploads /app/exports
|
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
|
RUN fc-cache -f /app/fonts || true
|
||||||
|
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||||
|
|||||||
Reference in New Issue
Block a user