| # ββ Build stage ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| FROM node:20-slim AS base | |
| WORKDIR /app | |
| # Copy package files first for better layer caching | |
| COPY package.json ./ | |
| RUN npm install --omit=dev | |
| # Copy everything else | |
| COPY . . | |
| # ββ Runtime βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| FROM node:20-slim | |
| # HuggingFace Spaces run as non-root user (uid 1000) | |
| RUN groupadd -g 1000 appuser && \ | |
| useradd -u 1000 -g appuser -s /bin/sh -m appuser | |
| WORKDIR /app | |
| # Copy installed modules and app code | |
| COPY --from=base /app /app | |
| RUN chown -R appuser:appuser /app | |
| USER appuser | |
| # HuggingFace requires the app to listen on port 7860 | |
| EXPOSE 7860 | |
| ENV PORT=7860 | |
| ENV NODE_ENV=production | |
| # Health check | |
| HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ | |
| CMD node -e "require('http').get('http://localhost:7860/health', r => process.exit(r.statusCode===200?0:1)).on('error',()=>process.exit(1))" | |
| CMD ["node", "server/index.js"] | |