Files
community-rule/Dockerfile
T
2026-05-23 19:35:38 -06:00

72 lines
3.1 KiB
Docker

# Production image: Next.js standalone output + Prisma, packaged for Cloudron.
# Build / push: ./scripts/docker-release.sh
# Install: cloudron install (reads CloudronManifest.json from repo root)
# See docs/guides/ops-backend-deploy.md §9.
FROM node:20-bookworm-slim AS base
WORKDIR /app
ENV NEXT_TELEMETRY_DISABLED=1
FROM base AS deps
RUN apt-get update -y && apt-get install -y openssl && rm -rf /var/lib/apt/lists/*
COPY package.json package-lock.json ./
# Copy the Prisma schema so the project's `postinstall` (which runs
# `prisma generate`) succeeds during install.
COPY prisma ./prisma
# `npm install` rather than `npm ci`:
# 1. `npm ci` strictly validates the lockfile and refuses when sub-tree
# resolutions drift (a recurring nuisance because the lockfile is
# generated on darwin-arm64 by default).
# 2. `npm install` reuses the lockfile when it can but tolerates
# platform-specific reshuffles for Linux-only optional deps
# (`lightningcss-linux-*-gnu`, `@tailwindcss/oxide-linux-*-gnu`,
# `@next/swc-linux-*-gnu`, etc.) that Next.js needs at build time.
RUN npm install --no-audit --fund=false
FROM base AS builder
RUN apt-get update -y && apt-get install -y openssl && rm -rf /var/lib/apt/lists/*
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# Standalone output omits TS sources the seed imports; bundle seed + JSON paths
# so `node prisma/seed.bundle.cjs` works in the slim runner (no tsx/lib/ tree).
RUN ./node_modules/.bin/esbuild prisma/seed.ts \
--bundle --platform=node --format=cjs \
--outfile=prisma/seed.bundle.cjs \
--external:@prisma/client
FROM base AS runner
# openssl: Prisma engines. gosu: privilege drop in start.sh after chown.
RUN apt-get update -y && apt-get install -y openssl gosu && rm -rf /var/lib/apt/lists/*
ENV NODE_ENV=production
# Reuse the `node` user (uid/gid 1000) shipped in node:20-bookworm-slim.
# Cloudron's localstorage addon mounts /app/data with root:root ownership at
# runtime; start.sh chowns it to node:node before dropping privileges.
COPY --from=builder --chown=node:node /app/public ./public
COPY --from=builder --chown=node:node /app/.next/standalone ./
COPY --from=builder --chown=node:node /app/.next/static ./.next/static
COPY --from=builder --chown=node:node /app/prisma ./prisma
# Facet/template seed JSON — NOT under /app/data (localstorage mount overlays that).
COPY --from=builder --chown=node:node /app/data ./seed-data
ENV SEED_DATA_DIR=/app/seed-data
# Prisma CLI (devDependency) is not in the Next.js standalone trace. Install
# globally in the runner so start.sh can run `prisma migrate deploy`.
RUN npm install -g prisma@6.19.3
# Cloudron's runtime rootfs is read-only except /tmp, /run, /app/data.
# Three marketing routes use ISR (`revalidate`) and write to .next/cache;
# redirect that path to /tmp/next-cache via a baked-in symlink so writes land
# on a writable mount at runtime.
RUN mkdir -p .next && ln -sfn /tmp/next-cache .next/cache
COPY --chown=node:node scripts/start.sh /start.sh
RUN chmod +x /start.sh
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
CMD ["/start.sh"]