dow-prod-tracker/Dockerfile
DJP 2b18c99296 Fix stuck deploy: seed deps missing from prod image + health check too strict
Caught on the first real deploy to optical-dev. Two separate bugs.

Dockerfile — runner stage was missing tsx + @prisma/adapter-pg + bcryptjs
   The Next.js standalone bundle covers the app, but prisma/seed-dow.ts
   is a separate .ts file executed via tsx (not bundled). Runner only
   explicitly installed prisma + dotenv, so `npm run db:seed` failed with
   "sh: tsx: not found" and deploys couldn't run the one-time seed.
   → Added tsx, @prisma/adapter-pg (seed uses PrismaPg directly), and
     bcryptjs (seed hashes the admin's temp password) to the
     `npm install --no-save` line in the runner stage. Adds ~15 MB to
     the final image — worth it for a working seed path.

/api/health was 503 pre-seed, which made deploy.sh unwillingly block itself
   The probe in deploy.sh uses `curl -sf` and treats any non-2xx as
   "not ready". The health endpoint flipped the entire `healthy` flag to
   false when `organizations` or `pipeline_templates` counted zero —
   meaning a freshly-migrated-but-not-yet-seeded app was classified as
   unhealthy, deploy.sh gave up at Step 6, and we never got to Step 7
   (Apache config) or Step 8 (UFW). End result: the URL 404'd because
   Apache wasn't proxying anything to the container.
   → Split liveness from readiness:
     - GET /api/health (default) — DB reachable, pgvector installed,
       AUTH_SECRET set, DEV_BYPASS off. Empty tables are reported as
       "warn" but do NOT 503. This is what deploy.sh waits on.
     - GET /api/health?strict=1 — same checks PLUS org + templates
       present. Use post-seed to verify everything landed.
   - Added a "mode" field ("liveness" | "strict") so which mode was
     used is visible in the response.
   - Pre-seed content-level checks now return status: "warn" with a
     hint to run `npm run db:seed`, instead of hard-failing.

Net effect for a fresh deploy:
  ./deploy.sh → builds, runs migrations, reports healthy once DB +
  env are good, configures Apache, DONE. Then you can
  `docker compose -p dow-prod-tracker exec app npm run db:seed`
  at your leisure.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 20:45:44 -04:00

71 lines
2.1 KiB
Docker

FROM node:22-alpine AS base
# FFmpeg for video transcoding (HLS), thumbnail extraction, and metadata
RUN apk add --no-cache ffmpeg
# Install dependencies only when needed
FROM base AS deps
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci --ignore-scripts
RUN npx prisma generate || true
# Rebuild source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Generate Prisma client
RUN npx prisma generate
# Build the Next.js app
RUN npm run build
# Production image
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
# Copy Next.js standalone output
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
# Copy Prisma schema, config, and migrations for runtime
COPY --from=builder /app/prisma ./prisma
COPY --from=builder /app/prisma.config.ts ./prisma.config.ts
COPY --from=builder /app/src/generated ./src/generated
# Install runtime deps needed for migrations + seed. The Next.js standalone
# bundle covers the app itself, but the seed script (prisma/seed-dow.ts) is
# a separate .ts file executed via tsx and needs its own module graph:
# prisma — the migrate-deploy CLI
# dotenv — prisma.config.ts imports dotenv/config
# tsx — runs the seed without an ahead-of-time compile
# @prisma/adapter-pg — the driver the seed instantiates directly
# bcryptjs — the seed hashes the admin's temp password
RUN npm install --no-save \
prisma@7.4.2 \
dotenv@17.3.1 \
tsx@4 \
@prisma/adapter-pg@7.4.2 \
bcryptjs@3
# Create uploads directories for media storage
RUN mkdir -p /data/uploads && chown nextjs:nodejs /data/uploads
RUN mkdir -p /app/public/uploads/revisions && chown -R nextjs:nodejs /app/public/uploads
USER nextjs
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
CMD ["sh", "-c", "./node_modules/.bin/prisma migrate deploy && node server.js"]