# Stage 1: Build Frontend FROM node:20-alpine AS frontend-build WORKDIR /app/frontend COPY frontend/package*.json ./ RUN npm ci COPY frontend/ . RUN npm run build # Stage 2: Build Backend FROM node:20-alpine AS backend-build WORKDIR /app/backend COPY backend/package*.json ./ RUN npm ci COPY backend/ . RUN npm run build # Stage 3: Production Image FROM node:20-alpine WORKDIR /app # Install nginx and supervisor RUN apk add --no-cache nginx supervisor # Copy Backend COPY --from=backend-build /app/backend/dist ./backend/dist COPY --from=backend-build /app/backend/node_modules ./backend/node_modules COPY --from=backend-build /app/backend/package.json ./backend/ # Copy Frontend COPY --from=frontend-build /app/frontend/dist ./frontend/dist # Nginx Config RUN mkdir -p /run/nginx COPY nginx.conf /etc/nginx/http.d/default.conf # Supervisor Config COPY supervisord.conf /etc/supervisord.conf # Create non-root user RUN addgroup -g 1001 -S appgroup && adduser -S appuser -u 1001 # Set permissions RUN chown -R appuser:appgroup /app /run/nginx /var/log/nginx /var/lib/nginx # Expose single port EXPOSE 10000 # Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://localhost:10000/api/health || exit 1 # Start with supervisor CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]