| # ── Stage 1: Build ──────────────────────────────────────────────────────────── | |
| FROM node:20-alpine AS builder | |
| WORKDIR /app | |
| COPY package.json package-lock.json* ./ | |
| RUN npm ci --ignore-scripts | |
| COPY tsconfig.json ./ | |
| COPY src/ ./src/ | |
| RUN npm run build | |
| # ── Stage 2: Run ────────────────────────────────────────────────────────────── | |
| FROM node:20-alpine AS runner | |
| WORKDIR /app | |
| # node:20-alpine already has a 'node' user with uid 1000 / gid 1000 | |
| # HF Spaces runs containers as uid 1000 – so we reuse the existing user | |
| RUN mkdir -p /data && chown -R node:node /data /app | |
| COPY --from=builder --chown=node:node /app/package.json /app/package-lock.json* ./ | |
| RUN npm ci --omit=dev --ignore-scripts | |
| COPY --from=builder --chown=node:node /app/dist/ ./dist/ | |
| USER node | |
| # Hugging Face Spaces default port | |
| ENV PORT=7860 | |
| ENV HOST=0.0.0.0 | |
| ENV NODE_ENV=production | |
| EXPOSE 7860 | |
| CMD ["node", "dist/index.js"] | |