# syntax=docker/dockerfile:1.6
#
# AEGIS CYBER — On-Prem Docker Image
# Multi-stage build. Stage 1 compiles the client (vite) and bundles the
# server (esbuild). Stage 2 ships only the artefacts needed at runtime
# plus node_modules (drizzle-kit lives in devDependencies and is used at
# first-boot for schema push, so we keep all deps in the runtime image).
#
# Build:    docker compose build
# Run:      docker compose up -d
# Logs:     docker compose logs -f app
# Shutdown: docker compose down

# ----- Stage 1: build ------------------------------------------------------
FROM node:20-alpine AS builder
WORKDIR /app

# System deps for native modules (bcryptjs is pure JS, pg is pure JS,
# but esbuild + vite are happier with python3 around).
RUN apk add --no-cache python3 make g++

COPY package.json package-lock.json ./
# `npm ci` for reproducible builds (matters for bank-bound deployments).
# Optional deps are INCLUDED here: rollup's platform-specific native binaries
# (@rollup/rollup-linux-x64-musl on Alpine) are declared as optional in the
# rollup package's own manifest but are required at runtime — `npm run build`
# crashes with MODULE_NOT_FOUND on rollup/dist/native.js without them.
RUN npm ci --no-audit --no-fund

COPY . .
RUN npm run build

# ----- Stage 2: runtime ----------------------------------------------------
FROM node:20-alpine AS runtime
WORKDIR /app

# dumb-init for clean SIGTERM forwarding; postgresql-client gives us
# pg_dump (used by the backup-service) and the psql wait probe in
# entrypoint.sh as a fallback.
RUN apk add --no-cache dumb-init postgresql16-client

ENV NODE_ENV=production
ENV PORT=5000

# Bring full node_modules from builder (drizzle-kit at runtime for db:push).
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/package-lock.json ./package-lock.json
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/migrations ./migrations
COPY --from=builder /app/shared ./shared
COPY --from=builder /app/drizzle.config.ts ./drizzle.config.ts
COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh

# Non-root user; pre-create the export + backup volume mount points so
# the named volumes get the right ownership on first mount.
RUN addgroup -S aegis && adduser -S aegis -G aegis \
    && mkdir -p /var/aegis/exports /var/aegis/backups \
    && chown -R aegis:aegis /var/aegis /app
USER aegis

EXPOSE 5000

# dumb-init reaps zombies and forwards SIGTERM cleanly so the graceful
# shutdown path in server/index.ts runs in full on `docker compose stop`.
ENTRYPOINT ["dumb-init", "--", "/usr/local/bin/entrypoint.sh"]
CMD ["node", "./dist/index.cjs"]
