# Multi-stage build for production-ready Etsy Finance Tracker with Nginx # Stage 1: Build the React client FROM node:18-alpine AS client-build WORKDIR /app/client # Copy client package files COPY client/package*.json ./ RUN npm ci --only=production # Copy client source and build COPY client/ ./ RUN npm run build # Stage 2: Build the Node.js server FROM node:18-alpine AS server-build WORKDIR /app/server # Copy server package files COPY server/package*.json ./ RUN npm ci --only=production # Copy server source and build COPY server/ ./ RUN npm run build # Stage 3: Production API server (no static files) FROM node:18-alpine AS production WORKDIR /app # Install dumb-init for proper signal handling and curl for health checks RUN apk add --no-cache dumb-init curl # Create non-root user for security RUN addgroup -g 1001 -S nodejs RUN adduser -S nodejs -u 1001 # Copy built server COPY --from=server-build --chown=nodejs:nodejs /app/server/dist ./server/ COPY --from=server-build --chown=nodejs:nodejs /app/server/node_modules ./server/node_modules/ COPY --from=server-build --chown=nodejs:nodejs /app/server/package*.json ./server/ # Create data directory for persistent storage RUN mkdir -p /app/data && chown nodejs:nodejs /app/data # Switch to non-root user USER nodejs # Expose API port (nginx will handle port 80) EXPOSE 8080 # Health check for API server HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost:8080/health || exit 1 # Start the API server ENTRYPOINT ["dumb-init", "--"] CMD ["node", "server/index.js"]