- Willkommens-Karten: gerendertes PNG (SVG → sharp) mit Avatar im Neon-Ring, Willkommens-Schriftzug und Member-Nummer; Fallback aufs bisherige Embed wenn das Rendering scheitert; Dockerfile installiert fonts-dejavu-core für die Text-Darstellung - Geburtstags-System: /geburtstag setzen|entfernen (birthdays-Tabelle), tägliche Runde ab 09:00 Europe/Berlin (Doppel-Post-Schutz über last_birthday_run), Gratulations-Embed + Tages-Rolle (wird am nächsten Morgen wieder abgeräumt); Kanal + Rolle im Community-Tab - Devlog-Permalinks: /devlogs/:id als eigene Seite (GET /api/devlogs/:id), Link-Symbol an jeder Karte, Link-kopieren-Button; der Server injiziert Open-Graph-Tags ins SPA-HTML — Devlog-Links zeigen Titel, Anriss und Bild, alle anderen Seiten bekommen Default-Tags (auch die Startseite) - Auto-Publish: maybeCrosspost() veröffentlicht Devlog-, Release-, Composer- und geplante Posts automatisch in Ankündigungs-Kanälen - brandEmbed: leere Avatar-URL crasht nicht mehr die Footer-Validierung Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
32 lines
862 B
Docker
32 lines
862 B
Docker
# EcoBot — Discord-Bot + Webinterface
|
|
# Stage 1: React-Frontend bauen
|
|
FROM node:22-slim AS frontend
|
|
WORKDIR /build
|
|
COPY frontend/package.json frontend/package-lock.json ./
|
|
RUN npm ci
|
|
COPY frontend ./
|
|
RUN npm run build
|
|
|
|
# Stage 2: Runtime (slim statt alpine: better-sqlite3 liefert glibc-Prebuilds)
|
|
FROM node:22-slim
|
|
|
|
# Fonts für die Willkommens-Karten (sharp/librsvg braucht installierte Schriften)
|
|
RUN apt-get update && apt-get install -y --no-install-recommends fonts-dejavu-core \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
WORKDIR /app
|
|
|
|
# Erst nur Manifest kopieren → Docker-Layer-Cache für npm ci
|
|
COPY package.json package-lock.json ./
|
|
RUN npm ci --omit=dev
|
|
|
|
COPY src ./src
|
|
COPY --from=frontend /build/dist ./frontend/dist
|
|
|
|
# Laufzeitdaten (SQLite) landen in /app/data → Volume
|
|
RUN mkdir -p /app/data
|
|
|
|
ENV NODE_ENV=production
|
|
|
|
CMD ["node", "src/index.js"]
|