# Stage 1: Install dependencies FROM node:22-slim AS deps RUN corepack enable && corepack prepare pnpm@latest --activate WORKDIR /app COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./ COPY frontend/package.json frontend/ COPY server/package.json server/ RUN pnpm install --frozen-lockfile # Cache-bust arg — pass --build-arg CACHE_BUST=$(date +%s) to force rebuild ARG CACHE_BUST=0 # Stage 2: Build frontend FROM deps AS build-fe ARG CACHE_BUST COPY frontend/ frontend/ RUN pnpm --filter frontend build # Stage 3: Build server FROM deps AS build-be ARG CACHE_BUST COPY server/ server/ RUN pnpm --filter server build # Stage 4: Production image FROM node:22-slim AS production RUN corepack enable && corepack prepare pnpm@latest --activate WORKDIR /app COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./ COPY server/package.json server/ RUN pnpm install --filter server --prod --frozen-lockfile # Copy built server COPY --from=build-be /app/server/dist server/dist # Copy built frontend into server's public dir COPY --from=build-fe /app/frontend/dist server/public # Data volume for SQLite RUN mkdir -p /app/server/data # Non-root user RUN groupadd --system botfights && useradd --system --gid botfights botfights \ && chown -R botfights:botfights /app USER botfights VOLUME /app/server/data ENV NODE_ENV=production ENV PORT=9100 EXPOSE 9100 HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ CMD node -e "fetch('http://localhost:9100/api/health').then(r=>{if(!r.ok)process.exit(1)}).catch(()=>process.exit(1))" CMD ["node", "--max-old-space-size=256", "server/dist/index.js"]