Files
d4rkbot/Dockerfile
T
D4rkst3randClaude Opus 5 484f2edc62
Deploy / check (push) Canceled after 0s
Deploy / deploy (push) Canceled after 0s
Radio: den Schliesscode festhalten, statt UDP zu behaupten
Die Meldung "ausgehendes UDP dicht" war geraten. Am 14.08.2026 im laufenden
Container gegengemessen, und sie stimmt nicht:

  UDP raus (DNS)              1.1.1.1:53                 4 ms
  UDP auf hohem Port (STUN)   stun.l.google.com:19302    9 ms
  TCP zum Sprachserver        c-fra13-...discord.media:2096  offen
  Verschluesselung            libsodium-wrappers 0.8.4 geladen

UDP kommt also raus, auch auf hohen Ports und mit Rueckweg durchs NAT. Der
Satz stand trotzdem da, weil "Weg enthaelt connecting" als Beweis genommen
wurde. Ist es nicht: in @discordjs/voice 0.18 faellt die Verbindung bei
*jedem* Websocket-Schluss ausser 4014 stumm nach "signalling" zurueck
(onNetworkingClose) und wirft den Schliesscode dabei weg. Ob der UDP-Teil je
begonnen hat, steht nirgends -- die Pruefung konnte den Unterschied nicht
sehen und hat trotzdem geurteilt.

Jetzt wird das Netzteil selbst mitgeschrieben: seine Schrittnummer
(NetworkingStatusCode, nachgeschlagen -- Websocket auf / Anmeldung /
UDP-Handschlag / Protokollwahl) und der Schliesscode. Nicht ueber `debug`,
denn das druckt Token und Sitzungsschluessel mit. Daraus folgt die Diagnose:

  stehen bei UDP-Handschlag  -> jetzt darf sie UDP sagen
  zu vor dem UDP-Teil        -> Sitzung (4006/4009), kein Netzproblem
  stehen bei Protokollwahl   -> Verschluesselung
  kein Mitschnitt            -> "Ursache offen". Nicht mehr "UDP".

Warum der UDP-Fall so aussieht, als haenge er: performIPDiscovery hat in
0.18 keine Zeitschranke, und die UDP-Keepalives werden nicht mehr
ausgewertet. Bleibt die Antwort aus, steht der Schritt, bis Discord den
Websocket zumacht.

Drei Sachen noch, die beim Nachsehen auffielen:

- Ein Fehler aus dem Netzteil hat den ganzen Prozess beendet. VoiceConnection
  reicht ihn als 'error' weiter, und ein EventEmitter ohne 'error'-Hoerer
  wirft. Genau dieser Weg ist im Fehlerfall offen -- die UDP-Erkennung meldet
  sich darueber. Jetzt gibt es einen Hoerer.
- schritte.endpunkt wurde bei jedem VOICE_SERVER_UPDATE ueberschrieben. Bei
  einem Rueckfall nennt Discord den Server erneut, also verdeckte die zweite
  Meldung den Endpunkt, an dem es scheiterte. Jetzt gesammelt, und fuer die
  Diagnose zaehlt der erste echte.
- tools/ landete nie im Abbild (COPY src ./src). Der Aufruf im Kopf von
  udp-pruefen.mjs -- "docker exec ... node tools/udp-pruefen.mjs" -- lief ins
  Leere. Jetzt kopiert das Dockerfile es mit.

Die neun Diagnose-Zweige sind gegen die exportierten Funktionen im Container
durchgespielt, nicht gegen eine Kopie.

Was weiter offen bleibt: eine Sperre speziell auf Zielports 50000-65535 ist
nicht widerlegt -- dafuer fehlt eine Gegenstelle, die dort antwortet. Der
naechste Fehlversuch sagt es von selbst.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-14 12:31:27 +02:00

39 lines
1.3 KiB
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),
# 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
CMD ["node", "src/index.js"]