From 602a56fc7f12a50c6b03eb726ab00ba6e3941bee Mon Sep 17 00:00:00 2001 From: Triple7 Date: Mon, 4 May 2026 04:49:02 -0700 Subject: [PATCH] Build frontend dist in Docker image for production deployment --- Dockerfile | 44 +++++++++++++++++++++++++++----------------- README.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 17 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1d0bd60..d3244f9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,32 +1,42 @@ +# syntax=docker/dockerfile:1 + # ───────────────────────────────────────────────────────────────────────────── -# SpectraCleanse AI – Backend Dockerfile -# Base: node:18-alpine | Exposes port 3001 +# SpectraCleanse AI – Production Dockerfile (builds frontend + backend runtime) # ───────────────────────────────────────────────────────────────────────────── -FROM node:18-alpine +FROM node:18-bookworm-slim AS builder +WORKDIR /app -# ExifTool requires Perl, which is not included in Alpine by default -RUN apk add --no-cache perl +COPY package.json package-lock.json ./ +RUN npm ci -# Create a non-root user to run the process -RUN addgroup -S appgroup && adduser -S appuser -G appgroup +COPY . . +RUN npm run build +FROM node:18-bookworm-slim AS runtime +ENV NODE_ENV=production WORKDIR /app -# Install dependencies first so Docker can cache this layer -COPY package*.json ./ -RUN npm ci --omit=dev +# exiftool-vendored requires Perl at runtime +RUN apt-get update \ + && apt-get install -y --no-install-recommends perl \ + && rm -rf /var/lib/apt/lists/* + +# Create non-root user +RUN groupadd --system appgroup && useradd --system --gid appgroup appuser + +COPY package.json package-lock.json ./ +RUN npm ci --omit=dev \ + && npm cache clean --force -# Copy application source COPY server.js ./ +COPY --from=builder /app/dist ./dist -# Runtime uploads directory (ephemeral; processed files are deleted after download) -# Persistent data directory for SQLite – mount a volume here in production -RUN mkdir -p uploads /data && chown -R appuser:appgroup /app uploads /data +# Runtime directories (uploads ephemeral; /data intended for SQLite volume mounts) +RUN mkdir -p /app/uploads /data \ + && chown -R appuser:appgroup /app /data -# Drop to non-root for all subsequent instructions and at runtime USER appuser EXPOSE 3001 - -CMD ["node", "server.js"] +CMD ["npm", "start"] diff --git a/README.md b/README.md index e7e7daa..d872ff3 100644 --- a/README.md +++ b/README.md @@ -45,3 +45,52 @@ The source code is available at [github.com/ChrisAdamsdevelopment/SpectraCleanse ## Contact Questions, partnerships, or enterprise enquiries: [hello@spectracleanse.com](mailto:hello@spectracleanse.com) + +--- + +## Docker production deployment + +This repository includes a multi-stage `Dockerfile` that builds the frontend and packages `dist/` into the final runtime image so `server.js` can serve the SPA in production. + +### Build image + +```bash +docker build -t spectracleanseai:latest . +``` + +### Run container + +```bash +docker run --rm -p 3001:3001 \ + -e NODE_ENV=production \ + -e JWT_SECRET=your_jwt_secret \ + -e STRIPE_SECRET_KEY=sk_live_xxx \ + -e STRIPE_WEBHOOK_SECRET=whsec_xxx \ + -e STRIPE_CREATOR_PRICE_ID=price_xxx \ + -e STRIPE_STUDIO_PRICE_ID=price_xxx \ + -e GEMINI_API_KEY=your_gemini_api_key \ + -e FRONTEND_URL=https://your-frontend-domain.example \ + -e DB_PATH=/data/spectra.db \ + -v spectracleanse_data:/data \ + spectracleanseai:latest +``` + +### Required production environment variables + +- `NODE_ENV=production` +- `JWT_SECRET` +- `STRIPE_SECRET_KEY` +- `STRIPE_WEBHOOK_SECRET` +- `STRIPE_CREATOR_PRICE_ID` +- `STRIPE_STUDIO_PRICE_ID` +- `GEMINI_API_KEY` +- `FRONTEND_URL` +- `DB_PATH` +- `REDIS_URL` (only if your deployment still uses Redis externally) + +### Stripe vs local mock checkout + +- Local development may use `ENABLE_MOCK_CHECKOUT=true` when Stripe variables are not set. +- Production must use real Stripe configuration; do not rely on mock checkout in production. + +Never commit real secrets to source control.