# TouchBase — single image runs both web (`pnpm start`) and worker # (`pnpm worker`). The compose file picks via `command:` override. # # Base: node:22-bookworm-slim — Debian-based for broad native-deps compat # (sharp, esbuild, etc.). We trade ~80MB image size for fewer surprises # than alpine. # ---------- deps: install all dependencies (incl. dev for build) ---------- FROM node:22-bookworm-slim AS deps WORKDIR /app # pnpm via corepack RUN corepack enable && corepack prepare pnpm@10.18.3 --activate COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ RUN pnpm install --frozen-lockfile # ---------- builder: prisma generate + next build ---------- FROM node:22-bookworm-slim AS builder WORKDIR /app RUN corepack enable && corepack prepare pnpm@10.18.3 --activate COPY --from=deps /app/node_modules ./node_modules COPY . . # Generate the Prisma client into src/generated/prisma — it's then bundled # by the Next build the same way the rest of `src/` is. RUN pnpm exec prisma generate # Next build uses Turbopack in dev but the production build is the regular # webpack pipeline; should work as-is in CI. ENV NEXT_TELEMETRY_DISABLED=1 RUN pnpm build # ---------- runner: minimal runtime image ---------- FROM node:22-bookworm-slim AS runner WORKDIR /app # Non-root user for the runtime RUN groupadd --system --gid 1001 nodejs \ && useradd --system --uid 1001 --gid nodejs nextjs # Install pnpm globally so it's on PATH for the non-root user without # corepack re-downloading into a per-user cache it can't write to. RUN npm install --global pnpm@10.18.3 ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED=1 # Copy everything we need: # - node_modules (for `next start`, `pnpm worker`/tsx, prisma CLI) # - .next build output # - public assets # - prisma schema + generated client # - source needed by the worker (scripts + src/lib + src/generated) # - package.json scripts COPY --from=deps --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/prisma ./prisma COPY --from=builder --chown=nextjs:nodejs /app/prisma.config.ts ./prisma.config.ts COPY --from=builder --chown=nextjs:nodejs /app/scripts ./scripts COPY --from=builder --chown=nextjs:nodejs /app/src/generated ./src/generated COPY --from=builder --chown=nextjs:nodejs /app/src/lib ./src/lib COPY --from=builder --chown=nextjs:nodejs /app/src/auth.ts ./src/auth.ts COPY --from=builder --chown=nextjs:nodejs /app/src/components ./src/components COPY --from=builder --chown=nextjs:nodejs /app/tsconfig.json ./tsconfig.json COPY --from=builder --chown=nextjs:nodejs /app/next.config.ts ./next.config.ts COPY --from=builder --chown=nextjs:nodejs /app/package.json ./package.json COPY --from=builder --chown=nextjs:nodejs /app/pnpm-lock.yaml ./pnpm-lock.yaml COPY --from=builder --chown=nextjs:nodejs /app/pnpm-workspace.yaml ./pnpm-workspace.yaml USER nextjs EXPOSE 3000 # Default to the web tier; `command:` override in compose runs the worker. CMD ["pnpm", "start"]