# syntax=docker/dockerfile:1 # Web app (Next.js 15). NEXT_PUBLIC_API_URL is inlined into the client bundle at # BUILD time — it must be passed as a build arg, not just a runtime env var. # Build context must be the repo root: docker build -f apps/web/Dockerfile . FROM node:20-alpine AS base RUN corepack enable && corepack prepare pnpm@9.12.0 --activate WORKDIR /app # ---- deps ---- FROM base AS deps COPY pnpm-lock.yaml pnpm-workspace.yaml package.json ./ COPY apps/api/package.json apps/api/ COPY apps/web/package.json apps/web/ COPY apps/generator/package.json apps/generator/ COPY apps/runner-template/package.json apps/runner-template/ COPY packages/auth/package.json packages/auth/ COPY packages/db/package.json packages/db/ COPY packages/llm/package.json packages/llm/ COPY packages/types/package.json packages/types/ RUN pnpm install --frozen-lockfile # ---- build ---- FROM deps AS build ARG NEXT_PUBLIC_API_URL=http://localhost:4000 ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL # Stripe publishable key — inlined into the client bundle so the embedded # checkout can initialise. Safe to expose (publishable, not secret). Empty # build = embedded checkout shows a "not configured" message until set. ARG NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY= ENV NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=$NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY ENV NEXT_TELEMETRY_DISABLED=1 COPY . . RUN pnpm --filter @bmm/web build # ---- runtime ---- FROM build AS runtime ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED=1 WORKDIR /app/apps/web EXPOSE 3001 # NOTE (INF-003): non-root `USER node` was reverted — `pnpm start` via corepack # can't reach its root-owned cache as the node user and the deploy health-check # doesn't cover web, so a broken web would deploy "green" but take the site down. # Re-enable only after switching the runtime CMD to invoke next directly # (node_modules/.bin/next) and smoke-testing the image locally. CMD ["pnpm", "start"]