| 1 | # syntax=docker/dockerfile:1
|
|---|
| 2 | # ──────────────────────────────────────────────────────────────────────────
|
|---|
| 3 | # Klonkt — self-host image. Multi-stage: compile native deps in a full
|
|---|
| 4 | # image, then a slim runtime. ffmpeg is bundled via ffmpeg-static
|
|---|
| 5 | # (npm), cwebp comes from the Debian 'webp' package.
|
|---|
| 6 | # ──────────────────────────────────────────────────────────────────────────
|
|---|
| 7 |
|
|---|
| 8 | # ---- builder: fetch native modules (better-sqlite3) + ffmpeg-static ----
|
|---|
| 9 | FROM node:20-bookworm AS builder
|
|---|
| 10 | WORKDIR /app
|
|---|
| 11 | # Build tools in case better-sqlite3 must build from source (otherwise prebuilt).
|
|---|
| 12 | RUN apt-get update && apt-get install -y --no-install-recommends python3 make g++ \
|
|---|
| 13 | && rm -rf /var/lib/apt/lists/*
|
|---|
| 14 | COPY package.json package-lock.json ./
|
|---|
| 15 | # Production deps; install scripts run (better-sqlite3 build + ffmpeg download).
|
|---|
| 16 | RUN npm ci --omit=dev
|
|---|
| 17 |
|
|---|
| 18 | # ---- runtime: slank image + cwebp ----
|
|---|
| 19 | FROM node:20-bookworm-slim AS runtime
|
|---|
| 20 | ENV NODE_ENV=production \
|
|---|
| 21 | PORT=3000
|
|---|
| 22 | WORKDIR /app
|
|---|
| 23 | # cwebp = image→WebP (optional in the app, but handy); ca-certificates
|
|---|
| 24 | # for outbound HTTPS (license server, SMTP, Google).
|
|---|
| 25 | RUN apt-get update && apt-get install -y --no-install-recommends webp ca-certificates \
|
|---|
| 26 | && rm -rf /var/lib/apt/lists/*
|
|---|
| 27 | # node_modules (incl. compiled better-sqlite3 + bundled ffmpeg) from builder.
|
|---|
| 28 | COPY --from=builder /app/node_modules ./node_modules
|
|---|
| 29 | # App source code.
|
|---|
| 30 | COPY . .
|
|---|
| 31 | # Persistent data lives here (DB, media, audio) — mount point for a volume.
|
|---|
| 32 | RUN mkdir -p storage/media storage/audio && chown -R node:node /app
|
|---|
| 33 | USER node
|
|---|
| 34 | EXPOSE 3000
|
|---|
| 35 | # Simple healthcheck via Node's built-in fetch (Node 20).
|
|---|
| 36 | HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
|
|---|
| 37 | CMD node -e "fetch('http://127.0.0.1:'+(process.env.PORT||3000)+'/').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
|
|---|
| 38 | CMD ["node", "src/server.js"]
|
|---|