profileShare

rasmusjy / roundtable

Read-only snapshot

No repository description.

main default branch 181 files Expires Sep 13, 2026, 9:06 AM
Dockerfile 2,894 bytes
1 # syntax=docker/dockerfile:1
2
3 # ---------------------------------------------------------------------------
4 # Roundtable — multi-stage build producing a standalone Next.js server image.
5 # Base is debian-slim (not alpine) so the Prisma engine "just works".
6 # ---------------------------------------------------------------------------
7 FROM node:20-bookworm-slim AS base
8 ENV PNPM_HOME=/pnpm
9 ENV PATH=$PNPM_HOME:$PATH
10 RUN corepack enable
11 RUN apt-get update \
12 && apt-get install -y --no-install-recommends openssl ca-certificates \
13 && rm -rf /var/lib/apt/lists/*
14 WORKDIR /app
15
16 # --- Install dependencies (cached on the lockfile) -------------------------
17 FROM base AS deps
18 COPY package.json pnpm-lock.yaml ./
19 RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
20
21 # --- Build the app (standalone output) -------------------------------------
22 FROM base AS builder
23 COPY --from=deps /app/node_modules ./node_modules
24 COPY . .
25 ENV NEXT_TELEMETRY_DISABLED=1
26 # No runtime secrets needed to compile; env is validated at runtime instead.
27 ENV SKIP_ENV_VALIDATION=1
28 # Produce the self-contained standalone server for the runtime stage.
29 ENV BUILD_STANDALONE=1
30 RUN pnpm prisma generate
31 RUN pnpm build
32
33 # --- Prisma CLI for the entrypoint ----------------------------------------
34 # The entrypoint applies the schema at boot, which needs the CLI and its whole
35 # dependency tree. Lifting that out of the pnpm store means chasing symlinks
36 # through one store directory per transitive package, so it is installed once
37 # more here with npm, whose flat layout copies as a single directory.
38 #
39 # The version is read from package.json, so it can never drift from the client
40 # the app was generated against.
41 FROM base AS prismacli
42 WORKDIR /prisma-cli
43 COPY package.json ./
44 RUN npm install --omit=dev --no-package-lock \
45 "prisma@$(node -p "require('./package.json').devDependencies.prisma")"
46
47 # --- Runtime image ---------------------------------------------------------
48 FROM base AS runner
49 ENV NODE_ENV=production
50 ENV NEXT_TELEMETRY_DISABLED=1
51 ENV PORT=3000
52 ENV HOSTNAME=0.0.0.0
53
54 RUN groupadd -g 1001 nodejs && useradd -u 1001 -g nodejs -m nextjs
55
56 # Standalone server + assets.
57 COPY --from=builder /app/public ./public
58 COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
59 COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
60
61 # Schema plus the CLI that applies it at boot. The CLI stays outside
62 # ./node_modules on purpose: a second @prisma directory beside the standalone
63 # bundle would shadow the generated client Next already traced into it, and the
64 # app would start against an empty client.
65 COPY --from=builder /app/prisma ./prisma
66 COPY --from=prismacli /prisma-cli/node_modules /prisma-cli/node_modules
67
68 COPY --chown=nextjs:nodejs docker/entrypoint.sh ./entrypoint.sh
69 RUN chmod +x ./entrypoint.sh
70
71 USER nextjs
72 EXPOSE 3000
73 CMD ["./entrypoint.sh"]
74