# =================================== # Stage 1: Build Frontend # =================================== FROM node:20-alpine AS frontend-builder WORKDIR /app/frontend # Copy package files COPY frontend/package*.json ./ # Install dependencies RUN npm ci # Copy frontend source COPY frontend/ ./ # Build frontend RUN npm run build # =================================== # Stage 2: Build Backend # =================================== FROM node:20-alpine AS backend-builder WORKDIR /app/backend # Install OpenSSL for Prisma RUN apk add --no-cache openssl # Copy package files COPY backend/package*.json ./ # Install dependencies (including dev for build) RUN npm ci # Copy backend source COPY backend/ ./ # Generate Prisma client RUN npx prisma generate # Build TypeScript RUN npm run build # =================================== # Stage 3: Production Runtime # =================================== FROM node:20-alpine AS production WORKDIR /app # Install OpenSSL for Prisma runtime and netcat for DB health check RUN apk add --no-cache openssl netcat-openbsd # Create non-root user RUN addgroup -g 1001 -S nodejs && \ adduser -S opencrm -u 1001 -G nodejs # Copy backend package files COPY backend/package*.json ./ # Install production dependencies + tsx for seed script RUN npm ci --omit=dev && npm install tsx # Copy Prisma schema and generate client COPY backend/prisma ./prisma RUN npx prisma generate # Copy built backend COPY --from=backend-builder /app/backend/dist ./dist # Copy built frontend to public directory COPY --from=frontend-builder /app/frontend/dist ./public # Copy seed file for factory reset COPY backend/prisma/seed.ts ./prisma/ # Copy entrypoint script COPY docker/entrypoint.sh ./entrypoint.sh # Create directories for uploads and backups RUN mkdir -p uploads backups && \ chmod +x entrypoint.sh && \ chown -R opencrm:nodejs /app # Switch to non-root user USER opencrm # Expose port EXPOSE 3001 # Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://localhost:3001/api/health || exit 1 # Start the application with entrypoint ENTRYPOINT ["./entrypoint.sh"]