# `--target api` or `--target dashboard` picks the image; each builds only what it needs, on one shared install. FROM node:24-alpine AS deps RUN corepack enable WORKDIR /app COPY package.json pnpm-lock.yaml pnpm-workspace.yaml tsconfig.base.json ./ COPY packages/shared/package.json packages/shared/ COPY apps/api/package.json apps/api/ COPY apps/dashboard/package.json apps/dashboard/ # The API's postinstall generates the Prisma client from the schema COPY apps/api/prisma/schema.prisma apps/api/prisma/ COPY apps/api/prisma.config.ts apps/api/ RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store pnpm install --frozen-lockfile COPY packages/shared packages/shared RUN pnpm --filter @kooltap/shared run build FROM deps AS api-build COPY apps/api apps/api RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store pnpm --filter @kooltap/api run build \ && pnpm --filter @kooltap/api deploy --prod --legacy /deploy/api FROM deps AS dashboard-build # NEXT_PUBLIC_* values are baked into the dashboard bundle at build time ARG NEXT_PUBLIC_API_URL=http://localhost:3001/api/v1 ARG NEXT_PUBLIC_SITE_URL=https://kooltap.com ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL NEXT_PUBLIC_SITE_URL=$NEXT_PUBLIC_SITE_URL NEXT_TELEMETRY_DISABLED=1 COPY apps/dashboard apps/dashboard RUN pnpm --filter @kooltap/dashboard run build # ---- API: migrates the database, then serves FROM node:24-alpine AS api WORKDIR /app ENV NODE_ENV=production IMAGE_DIR=/data/images # The built API with its production dependencies, migrations and email templates COPY --from=api-build /deploy/api ./ RUN mkdir -p /data/images && chown node:node /data/images USER node VOLUME /data/images EXPOSE 3001 CMD ["sh", "-c", "npx prisma migrate deploy && node dist/main.js"] # ---- Dashboard: Next's standalone server FROM node:24-alpine AS dashboard WORKDIR /app ENV NODE_ENV=production NEXT_TELEMETRY_DISABLED=1 PORT=3000 HOSTNAME=0.0.0.0 COPY --from=dashboard-build --chown=node:node /app/apps/dashboard/.next/standalone ./ COPY --from=dashboard-build --chown=node:node /app/apps/dashboard/.next/static ./apps/dashboard/.next/static COPY --from=dashboard-build --chown=node:node /app/apps/dashboard/public ./apps/dashboard/public USER node EXPOSE 3000 CMD ["node", "apps/dashboard/server.js"]