# Multi-stage Dockerfile for sirius-ui with development and production stages # # system-monitor and administrator are built in this file (no external GHCR base image). # ───────────────────────────────────────────────────────────────────────────── # Utility binaries: system-monitor + administrator # ───────────────────────────────────────────────────────────────────────────── FROM golang:1.24-alpine AS utility-go-binaries RUN apk add --no-cache git ca-certificates tzdata RUN git clone https://github.com/SiriusScan/app-system-monitor.git /tmp/system-monitor && \ cd /tmp/system-monitor && \ go mod download && \ CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o /usr/local/bin/system-monitor main.go && \ rm -rf /tmp/system-monitor RUN git clone https://github.com/SiriusScan/app-administrator.git /tmp/administrator && \ cd /tmp/administrator && \ go mod download && \ CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o /usr/local/bin/administrator main.go && \ rm -rf /tmp/administrator # ───────────────────────────────────────────────────────────────────────────── # Base stage: common Node.js dependencies # ───────────────────────────────────────────────────────────────────────────── FROM node:18-alpine AS base # Install system and native build dependencies for all architectures. # bcrypt may fall back to node-gyp compilation (notably on arm64/musl), which # requires Python + make + g++ at install time. RUN apk add --no-cache \ libc6-compat \ openssl \ ca-certificates \ git \ python3 \ make \ g++ WORKDIR /app # Copy package files COPY package*.json ./ COPY bun.lockb* ./ # Replace bun commands with npm/npx equivalents for compatibility COPY package.json package.json.bak RUN sed -i 's/bunx prisma generate/npx prisma generate/g' package.json && \ sed -i 's/bun next/npx next/g' package.json && \ sed -i 's/bun run/npm run/g' package.json # Clone sirius-nse repository for NSE scripts (needed by scanner profile management) ARG SIRIUS_NSE_COMMIT_SHA=main RUN mkdir -p /sirius-nse && \ git clone https://github.com/SiriusScan/sirius-nse.git /sirius-nse && \ cd /sirius-nse && \ git checkout ${SIRIUS_NSE_COMMIT_SHA} && \ echo "Cloned sirius-nse ($(git rev-parse --short HEAD))" # ───────────────────────────────────────────────────────────────────────────── # Development stage # ───────────────────────────────────────────────────────────────────────────── FROM base AS development # Non-root user: chown /app while it is still small (package files only from base). # Avoids chown -R over node_modules after npm install (very slow on Docker Desktop). RUN addgroup --system --gid 1001 nodejs && \ adduser --system --uid 1001 nextjs && \ chown -R nextjs:nodejs /app ENV NPM_CONFIG_CACHE=/app/.npm-cache EXPOSE 3000 ENV NODE_ENV=development ENV NEXT_TELEMETRY_DISABLED=1 USER nextjs RUN npm install COPY --chown=nextjs:nodejs . . RUN npx prisma generate # Ensure image start-dev.sh wins over build context and has unix line endings. USER root COPY start-dev.sh /app/start-dev.sh RUN sed -i 's/\r$//' /app/start-dev.sh && chmod +x /app/start-dev.sh && \ chown nextjs:nodejs /app/start-dev.sh USER nextjs CMD ["/bin/sh", "/app/start-dev.sh"] # ───────────────────────────────────────────────────────────────────────────── # Builder stage: compile Next.js application # ───────────────────────────────────────────────────────────────────────────── FROM base AS builder ARG NEXT_PUBLIC_CLIENTVAR COPY . . # Remove .env files that interfere with Docker environment variables RUN rm -f .env .env.local .env.development .env.production # Install dependencies (production + dev for building) RUN npm install # Generate Prisma client RUN npx prisma generate ENV NEXT_TELEMETRY_DISABLED=1 ENV NEXT_PUBLIC_CLIENTVAR=${NEXT_PUBLIC_CLIENTVAR} ENV SKIP_ENV_VALIDATION=1 ENV SIRIUS_BUILD_STAGE=docker-build # Inject ignoreBuildErrors flags for Docker build so TS/ESLint errors don't block RUN cp next.config.mjs next.config.mjs.bak && \ node -e "const fs=require('fs');const p='next.config.mjs';let c=fs.readFileSync(p,'utf8');c=c.replace(' swcMinify: true,',' swcMinify: true,\n typescript: { ignoreBuildErrors: true },\n eslint: { ignoreDuringBuilds: true },');fs.writeFileSync(p,c);" && \ npx next build # ───────────────────────────────────────────────────────────────────────────── # Production runtime stage # ───────────────────────────────────────────────────────────────────────────── FROM node:18-alpine AS production RUN apk add --no-cache \ libc6-compat \ openssl \ ca-certificates # Non-root user RUN addgroup --system --gid 1001 nodejs && \ adduser --system --uid 1001 nextjs WORKDIR /app # Create system-monitor directory RUN mkdir -p /system-monitor COPY --chown=nextjs:nodejs --from=utility-go-binaries /usr/local/bin/system-monitor /system-monitor/system-monitor COPY --chown=nextjs:nodejs --from=utility-go-binaries /usr/local/bin/administrator /app/administrator RUN chmod +x /system-monitor/system-monitor /app/administrator # Copy built Next.js application from builder stage (ownership set during copy — no full-tree chown) COPY --chown=nextjs:nodejs --from=builder /app/public ./public COPY --chown=nextjs:nodejs --from=builder /app/.next ./.next COPY --chown=nextjs:nodejs --from=builder /app/node_modules ./node_modules COPY --chown=nextjs:nodejs --from=builder /app/src ./src COPY --chown=nextjs:nodejs --from=builder /app/prisma ./prisma COPY --chown=nextjs:nodejs --from=builder /app/package.json ./package.json COPY --chown=nextjs:nodejs --from=builder /app/next.config.mjs ./next.config.mjs COPY --chown=nextjs:nodejs start-prod.sh /app/start-prod.sh RUN sed -i 's/\r$//' /app/start-prod.sh && chmod +x /app/start-prod.sh USER nextjs EXPOSE 3000 ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED=1 CMD ["/app/start-prod.sh"]