deploy: Dockerfile, entrypoint, standalone output, dockerignore

This commit is contained in:
2026-08-15 18:11:41 -04:00
parent e709de01d4
commit cbea5e8fa4
4 changed files with 110 additions and 0 deletions
+66
View File
@@ -0,0 +1,66 @@
# MapleBrief — production image
# Multi-stage: deps -> build -> minimal runner
# (Debian base: Prisma engines need glibc; Alpine breaks the schema/query engine.)
#
# Build args / secrets:
# NEXT_PUBLIC_ADSENSE_CLIENT_ID — AdSense client id baked into the build
# (empty -> ads hidden, app still works)
# Runtime env:
# ADMIN_API_KEY — admin/auth key (fail-closed 401 if empty)
# OLLAMA_BASE / provider — LLM endpoints (or configure in admin UI)
# DATABASE_URL defaults to file:/data/dev.db (volume-mounted)
# Optional: bake the real AdSense client id at build time (empty -> ads hidden)
ARG NEXT_PUBLIC_ADSENSE_CLIENT_ID=""
FROM node:22-slim AS deps
WORKDIR /app
RUN apt-get update -qq && apt-get install -yq --no-install-recommends openssl ca-certificates > /dev/null && rm -rf /var/lib/apt/lists/*
COPY package.json package-lock.json ./
RUN npm ci --no-audit --no-fund
FROM node:22-slim AS build
WORKDIR /app
# inherit the global value (set via --build-arg); empty -> placeholder ads
ARG NEXT_PUBLIC_ADSENSE_CLIENT_ID
RUN apt-get update -qq && apt-get install -yq --no-install-recommends openssl ca-certificates > /dev/null && rm -rf /var/lib/apt/lists/*
# Absolute path avoids Prisma resolving relative SQLite URLs against the
# schema dir (which would double up into prisma/prisma/...).
ENV DATABASE_URL="file:/app/fresh.db"
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Verify migrations apply to a fresh DB, then stage the migrated empty DB at
# the exact path the runner copies.
RUN npx prisma generate \
&& npx prisma migrate deploy \
&& cp /app/fresh.db prisma/fresh.db \
&& NEXT_PUBLIC_SITE_URL="https://news.krisforbes.ca" \
NEXT_PUBLIC_SITE_NAME="MapleBrief" \
NEXT_PUBLIC_SITE_DESCRIPTION="Synthesized Canadian news briefings" \
NEXT_PUBLIC_ADSENSE_CLIENT_ID="${NEXT_PUBLIC_ADSENSE_CLIENT_ID}" \
NEXT_PUBLIC_SHOW_SIDEBAR_ADS="false" \
npm run build \
&& rm -f /app/fresh.db prisma/fresh.db-journal prisma/fresh.db-shm
# (prisma/fresh.db kept above for the runner stage copy)
FROM node:22-slim AS runner
WORKDIR /app
RUN apt-get update -qq && apt-get install -yq --no-install-recommends curl > /dev/null && rm -rf /var/lib/apt/lists/*
# runtime user (guard: node slim images don't always ship one)
RUN id app 2>/dev/null || useradd -m -s /bin/sh app
# pre-create the data dir (volume replaces it at runtime) with app ownership
RUN mkdir -p /data && chown -R app:app /data
USER app
# Next standalone server
COPY --chown=app:app --from=build /app/.next/standalone ./
# static chunks + public assets (standalone does not auto-copy these)
COPY --chown=app:app --from=build /app/.next/static ./.next/static
COPY --chown=app:app --from=build /app/public ./public
# pre-migrated clean database snapshot (entrypoint copies it to /data on first boot)
COPY --chown=app:app --from=build /app/prisma/fresh.db ./seed-dev.db
COPY --chown=app:app entrypoint.sh ./entrypoint.sh
RUN chmod +x entrypoint.sh
ENV PORT=3000
ENV DATABASE_URL="file:/data/dev.db"
EXPOSE 3000
ENTRYPOINT ["./entrypoint.sh"]