# syntax=docker/dockerfile:1 # ---- deps: install once, reused by the builder layer ----------------------- FROM node:24-alpine AS deps WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci # ---- builder: `next build` with output: "standalone" ----------------------- FROM node:24-alpine AS builder WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . # NEXT_PUBLIC_* values are inlined into the client bundle at build time — # there is no way to change them later, so they must be passed as build args # (see docker-compose.yml, or `docker build --build-arg NEXT_PUBLIC_...=...`). ARG NEXT_PUBLIC_GOOYAL_ACCOUNTS_BASE_URL ARG NEXT_PUBLIC_GOOYAL_CLIENT_ID ARG NEXT_PUBLIC_GOOYAL_CLIENT_SECRET ARG NEXT_PUBLIC_GOOYAL_OAUTH_SCOPE ENV NEXT_PUBLIC_GOOYAL_ACCOUNTS_BASE_URL=$NEXT_PUBLIC_GOOYAL_ACCOUNTS_BASE_URL \ NEXT_PUBLIC_GOOYAL_CLIENT_ID=$NEXT_PUBLIC_GOOYAL_CLIENT_ID \ NEXT_PUBLIC_GOOYAL_CLIENT_SECRET=$NEXT_PUBLIC_GOOYAL_CLIENT_SECRET \ NEXT_PUBLIC_GOOYAL_OAUTH_SCOPE=$NEXT_PUBLIC_GOOYAL_OAUTH_SCOPE # Server-only vars are never read at build time (every route that touches them # is dynamic — cookies()/no-store fetches — so nothing runs during # prerendering), but a couple of modules validate them at import time # (e.g. session.ts throws if SESSION_SECRET is missing), so the build still # needs *some* value present. Real values are supplied at container runtime # instead (see docker-compose.yml / `docker run --env-file`) — never bake a # real secret into an image layer. ENV WINOFY_API_BASE_URL=https://placeholder.invalid/api \ GOOYAL_ACCOUNTS_BASE_URL=https://placeholder.invalid \ GOOYAL_CLIENT_ID=placeholder \ GOOYAL_CLIENT_SECRET=placeholder \ GOOYAL_OAUTH_SCOPE=placeholder \ SESSION_SECRET=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= RUN npm run build # ---- runner: minimal production image --------------------------------------- FROM node:24-alpine AS runner WORKDIR /app ENV NODE_ENV=production \ PORT=3000 \ HOSTNAME=0.0.0.0 RUN addgroup -g 1001 -S nodejs && adduser -S nextjs -u 1001 COPY --from=builder /app/public ./public COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static USER nextjs EXPOSE 3000 CMD ["node", "server.js"]