Add full Docker deployment: setup.sh, update.sh, healthcheck, TURN support

- setup.sh: interactive/non-interactive one-shot installer (build, DB
  healthcheck, migrate, seed, start), idempotent secret generation, NPM
  reverse-proxy network auto-detection and optional join, optional
  AUTO_UPDATE cron install.
- update.sh: release-tag-gated updates only (never bare main), DB backup
  with retention before every update, lock file against concurrent runs,
  automatic code rollback on failed post-update healthcheck.
- Dockerfile: multi-stage build, non-root user, built-in HEALTHCHECK against
  the new /api/health route, wholesale COPY so new source dirs (e.g.
  scripts/) never silently go missing at runtime.
- docker-compose.yml: internal anouma-network (configurable), named volume
  for Postgres, app depends_on postgres healthy, no unnecessary published
  ports; docker-compose.override.yml.example documents joining an existing
  NPM network without ever touching NPM itself.
- Fix host-detection: isHost was Boolean(user), wrongly granting host
  privileges to logged-in customers; now checks user.collection === "users".
- Wire configurable STUN/TURN servers through to the WebRTC client
  (lib/meeting/iceServers.ts) so a TURN server can be added later via env
  vars only, no code changes.
- DEPLOYMENT.md, updated README.md and .env.example documenting the whole
  flow: NPM integration, env vars, WebRTC, updates, backups, rollback.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-25 21:50:28 +02:00
co-authored by Claude Sonnet 5
parent d3d53e68a9
commit 50c39a70e0
16 changed files with 886 additions and 68 deletions
+21 -19
View File
@@ -1,16 +1,19 @@
# Runs a custom Node server (server.ts) for the WebRTC signaling WebSocket,
# so this can't use Next's "standalone" output — we ship the full app +
# node_modules instead. DATABASE_URI/PAYLOAD_SECRET etc. are only needed at
# runtime, not at build time (see docker-compose.yml and .env.example).
# Multi-stage build for the ANOUMA app (Next.js + Payload CMS + WebRTC
# signaling, all served by the custom server.ts — see next.config.ts for why
# this can't use Next's "standalone" output). DATABASE_URI/PAYLOAD_SECRET/etc.
# are only needed at *runtime*, not at build time (see docker-compose.yml and
# .env.example) — this image builds without a database connection.
FROM node:22-alpine AS base
# ---- deps: install once, cached as its own layer -------------------------
FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
# ---- builder: full source + production build ------------------------------
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
@@ -18,6 +21,7 @@ COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build
# ---- runner: the actual runtime image --------------------------------------
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
@@ -26,21 +30,16 @@ ENV NEXT_TELEMETRY_DISABLED=1
RUN addgroup --system --gid 1001 nodejs \
&& adduser --system --uid 1001 nextjs
COPY --from=builder --chown=nextjs:nodejs /app/node_modules ./node_modules
COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/server.ts ./server.ts
COPY --from=builder --chown=nextjs:nodejs /app/lib ./lib
COPY --from=builder --chown=nextjs:nodejs /app/payload.config.ts ./payload.config.ts
COPY --from=builder --chown=nextjs:nodejs /app/collections ./collections
COPY --from=builder --chown=nextjs:nodejs /app/globals ./globals
COPY --from=builder --chown=nextjs:nodejs /app/access ./access
COPY --from=builder --chown=nextjs:nodejs /app/fields ./fields
COPY --from=builder --chown=nextjs:nodejs /app/components ./components
COPY --from=builder --chown=nextjs:nodejs /app/next.config.ts ./next.config.ts
COPY --from=builder --chown=nextjs:nodejs /app/tsconfig.json ./tsconfig.json
COPY --from=builder --chown=nextjs:nodejs /app/package.json ./package.json
RUN mkdir -p media && chown nextjs:nodejs media
# Copied wholesale (not a hand-picked list of directories) so newly added
# source folders (collections, scripts, lib/*, components/*, ...) are never
# silently missing at runtime — .dockerignore already excludes what doesn't
# belong in the image (node_modules is re-added explicitly below, .next is
# the build output we do want).
COPY --from=builder --chown=nextjs:nodejs /app /app
# Writable at runtime, independent of the image — actual data lives in the
# Docker volumes mounted over these paths (see docker-compose.yml).
RUN mkdir -p media backups && chown -R nextjs:nodejs media backups
USER nextjs
@@ -48,4 +47,7 @@ EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME=0.0.0.0
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
CMD node -e "fetch('http://127.0.0.1:3000/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
CMD ["npm", "start"]