Files
KenzoandClaude Opus 5 1a7a4f8a02
ci/woodpecker/push/woodpecker Pipeline was successful
perf(ci): Builds beschleunigen und kaputtes sharp reparieren
Nur bauen was sich geaendert hat:
- deploy_backend laeuft nur bei Aenderungen unter backend/, deploy_frontend
  nur bei src/, public/ und den Frontend-Konfigdateien. Die haeufigsten
  Commits sind Inhaltsaenderungen aus dem CMS und fassen nur src/ und
  public/ an - die brauchen kein Backend-Deployment mehr.
- Der Abhaengigkeits-Audit laeuft nur noch, wenn sich package.json oder
  package-lock.json aendern. Sonst kam bei jedem Inhalts-Commit derselbe
  Bericht nach Discord.
- "[ALL]" in der Commit-Message erzwingt weiterhin den vollen Durchlauf.

Build-Kontext:
- Es gab kein .dockerignore im Root. Bei jedem Frontend-Deploy wanderte
  das komplette Repo zum Fly-Remote-Builder, inklusive 50 MB Git-Historie
  und des gesamten Backends. 98 MB -> 47 MB.
- Zwei tote Zeilen im Frontend-Dockerfile entfernt: ein Root-styles/ gibt
  es nicht und /styles/ wird als URL nirgends verwendet.

Backend-Image:
- npm ci lief in beiden Stages, better-sqlite3 wurde also doppelt
  uebersetzt. Jetzt einmal im Builder, danach npm prune --omit=dev und die
  fertigen node_modules wandern weiter.
- Die Build-Werkzeuge sind raus aus der Laufzeit-Stage. Das apk del vorher
  hat sie nur unsichtbar gemacht, die Layer blieben im Image.
- Ohne Cache lokal: 1:31 -> 0:29. Image: 845 MB -> 312 MB.

sharp war die ganze Zeit kaputt:
- backend/package-lock.json enthielt als einziges Plattform-Binary
  @img/sharp-win32-x64, das Lockfile stammt von einer Windows-Maschine.
  npm ci installiert strikt nach Lockfile, auf Alpine kam damit gar kein
  sharp-Binary an. Der Upload fiel jedes Mal auf den Fallback zurueck:
  keine Verkleinerung auf 1600px, keine WebP-Wandlung, das Originalbild
  landete unveraendert im Repo. Genau deshalb sind die Bilder so gross -
  in der Historie liegen entsprechend .jpeg statt .webp.
- Lockfile mit allen Plattformvarianten neu aufgeloest. Keine einzige
  bestehende Paketversion aendert sich dabei; dazugekommen sind die
  Binaries, weggefallen sind 12 Postgres-Pakete, die drizzle-kit optional
  mitzieht und die hier niemand benutzt.
- vips aus dem Image entfernt, sharp bringt seit 0.33 sein eigenes libvips
  mit.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-08-11 13:13:52 +02:00

62 lines
1.9 KiB
Docker

# Multi-stage build for Gallus CMS Backend
# Stage 1: Builder
# Hier werden die nativen Module EINMAL uebersetzt. Vorher lief npm ci in
# beiden Stages, better-sqlite3 wurde also doppelt kompiliert.
FROM node:20-alpine AS builder
WORKDIR /app
# Nur fuer better-sqlite3 - fuer musl gibt es davon keine Fertigbauten.
# sharp ab 0.33 bringt eigene Binaries samt libvips mit, vips-dev wird
# dadurch nicht mehr gebraucht.
RUN apk add --no-cache python3 make g++
# Eigener Layer: bleibt im Cache, solange sich das Lockfile nicht aendert
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Dev-Abhaengigkeiten entfernen. Was uebrig bleibt, ist fertig uebersetzt
# und wandert unveraendert ins Laufzeit-Image.
RUN npm prune --omit=dev
# Stage 2: Production
FROM node:20-alpine
WORKDIR /app
# git fuer simple-git, sqlite fuer die CLI. Keine Build-Werkzeuge mehr -
# die blieben vorher als Layer im Image liegen, auch nach dem apk del.
RUN apk add --no-cache git sqlite
COPY --from=builder /app/package*.json ./
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/migrate-production.js ./migrate-production.js
COPY --from=builder /app/data/images ./data/images
# Create directories and ensure proper permissions
RUN mkdir -p /app/workspace /app/data && chown -R node:node /app
# Switch to non-root user
USER node
# Expose port
EXPOSE 8080
# Set environment
ENV NODE_ENV=production
ENV PORT=8080
ENV DATABASE_PATH=/app/data/gallus_cms.db
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node -e "require('http').get('http://localhost:8080/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"
# Run DB migrations if present, then start application
CMD ["/bin/sh", "-lc", "mkdir -p /app/data/images/events /app/data/images/gallery && [ -f dist/migrate.js ] && node dist/migrate.js || true; node dist/index.js"]