Files
Aether/deploy/Dockerfile
T
HoneyandClaude Opus 5 428fd2672c docs(env): Beispieldateien kürzen, Erklärungen ins README
Die beiden .env.example zusammen waren 251 Zeilen für 40 Schlüssel – gut
gemeint, aber niemand liest einen Absatz pro Variable. Jetzt eine Zeile je
Schlüssel (58 + 89), die Begründungen stehen im README unter
'Einstellungen', gebündelt als die sieben Dinge, die nicht beim Start
auffallen, sondern später.

Dabei durch einen echten Start aus den Beispieldateien gefunden:
STORAGE_PATH fehlte, Vorgabe ./data wird im Container zu /app/data, und
der Start endete in 'mkdir /app/data: permission denied'. Das Abbild setzt
STORAGE_PATH und TMP_PATH jetzt selbst – es kennt seine Verzeichnisse
besser als eine Beispieldatei. Eine .env darf weiter überschreiben.

Geprüft: jeder Schlüssel, den die Anwendung liest, steht weiterhin in
deploy/.env.example; eine frische Instanz startet allein aus den beiden
Beispieldateien.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 11:27:31 +02:00

69 lines
3.3 KiB
Docker
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ── Stage 1: Frontend build ───────────────────────────────────────────────────
FROM node:20-alpine AS frontend-builder
WORKDIR /app/frontend
COPY frontend/package*.json ./
RUN npm ci
COPY frontend/ ./
RUN npm run build
# ── Stage 2: Backend build ────────────────────────────────────────────────────
FROM golang:1.25-alpine AS backend-builder
WORKDIR /app
RUN apk add --no-cache git
COPY backend/go.mod backend/go.sum ./
RUN go mod download
COPY backend/ ./
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o aether ./cmd/aether
# ── Stage 3: Final image ──────────────────────────────────────────────────────
FROM alpine:3.20
# ocrmypdf, tesseract und poppler machen den Inhalt von PDFs und Scans
# durchsuchbar (internal/documents). Sie wiegen zusammen rund 330 MB – der
# Löwenanteil des Images. Wer das nicht braucht, kann die zweite apk-Zeile
# streichen und OCR_ENABLED=false setzen; der Server prüft beim Start selbst,
# ob die Programme da sind, und läuft sonst ohne Volltextsuche weiter.
#
# tesseract-ocr-data-deu/-eng sind die Sprachmodelle. Ohne sie startet
# tesseract zwar, erkennt aber nichts – das Paket tesseract-ocr allein bringt
# keine mit.
RUN apk add --no-cache ca-certificates tzdata && \
apk add --no-cache ocrmypdf tesseract-ocr tesseract-ocr-data-deu \
tesseract-ocr-data-eng poppler-utils && \
addgroup -S aether && adduser -S aether -G aether && \
mkdir -p /data/users /data/thumbs /data/tmp && \
chown -R aether:aether /data
WORKDIR /app
# Wo die Blobs liegen. Steht **hier**, nicht nur in der .env: Die Voreinstellung
# im Code ist "./data" – richtig für ein Binary, das man von Hand startet,
# falsch im Container, wo daraus /app/data würde. Genau das ist beim ersten
# Aufbau aus der schlanken .env passiert: Migrationen liefen durch, dann
# "mkdir /app/data: permission denied". Das Abbild kennt seine eigene
# Verzeichnisstruktur besser als jede Beispieldatei; eine .env darf es
# weiterhin überschreiben.
ENV STORAGE_PATH=/data \
TMP_PATH=/data/tmp
# Tesseract vermisst beim allerersten Aufruf die OpenCL-Geräte und schreibt
# dabei einen langen Diagnoseblock nach stderr. ocrmypdf ruft davor
# `tesseract --list-langs` auf und liest die Antwort – der Block bringt seinen
# Parser aus dem Tritt, und der Aufruf endet mit „Tesseract failed to report
# available languages" (Exit 3).
#
# Das Ergebnis der Vermessung landet als .dat im Arbeitsverzeichnis; ab dann ist
# die Ausgabe kurz genug. Ohne diese Zeile scheitert deshalb genau das erste
# Dokument nach jedem Neustart eines frischen Containers – gemessen, nicht
# vermutet: Versuch 1 Exit 3, Versuch 2 erfolgreich. Der Wiederholungszähler
# fängt es zwar auf, aber ein Fehlschlag, den man einbauen kann, gehört nicht
# in den Log.
RUN tesseract --list-langs >/dev/null 2>&1 || true
COPY --from=backend-builder /app/aether ./aether
COPY --from=frontend-builder /app/frontend/dist ./static
RUN chown -R aether:aether /app
USER aether
EXPOSE 8080
ENTRYPOINT ["./aether"]