# 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), # git für die Repo-Backups (git clone --mirror + bundle), # ffmpeg fürs Radio: es holt den MP3-Strom und gibt direkt Ogg/Opus aus — damit # braucht es keine Opus-Bibliothek in Node, die erst gebaut werden müsste RUN apt-get update && apt-get install -y --no-install-recommends fonts-dejavu-core git ffmpeg \ && 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 # Die Prüfwerkzeuge müssen dort laufen, wo der Fehler auftritt — im Container. # Ohne diese Zeile lief `docker exec … node tools/udp-pruefen.mjs` ins Leere, # obwohl genau das im Kopf des Skripts steht. COPY tools ./tools COPY --from=frontend /build/dist ./frontend/dist # Laufzeitdaten (SQLite) landen in /app/data → Volume RUN mkdir -p /app/data ENV NODE_ENV=production # Ohne diese Zeile weiss Docker nur, DASS der Prozess laeuft — nicht, ob der # Bot noch mit Discord verbunden ist. Genau das beantwortet /health. # # `curl` und `wget` fehlen im slim-Abbild (nachgemessen), also Node selbst. # Die Schonfrist ist grosszuegig: der Anmeldevorgang bei Discord dauert, und # ein Neustart soll nicht als Ausfall gelten. HEALTHCHECK --interval=30s --timeout=5s --start-period=45s --retries=3 \ CMD node -e "fetch('http://127.0.0.1:'+(process.env.HTTP_PORT||3080)+'/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))" CMD ["node", "src/index.js"]