# Production Dockerfile for Frontend Web App # Optimized for smaller size, security, and performance # Build stage FROM node:20-alpine AS builder WORKDIR /app # Install build dependencies only RUN apk add --no-cache libc6-compat # Copy package files first for better caching COPY package*.json ./ # Install dependencies (this layer will be cached if package*.json don't change) RUN npm ci --only=production=false && \ npm cache clean --force # Copy source code COPY . . # Build arguments for environment variables ARG VITE_API_URL ARG VITE_WS_URL ARG VITE_STREAM_URL ARG VITE_APP_ENV=production # Set build-time environment variables ENV VITE_API_URL=${VITE_API_URL} ENV VITE_WS_URL=${VITE_WS_URL} ENV VITE_STREAM_URL=${VITE_STREAM_URL} ENV VITE_APP_ENV=${VITE_APP_ENV} ENV NODE_ENV=production # Build the application with optimizations RUN npm run build && \ # Verify build output exists test -f dist/index.html || { echo "ERROR: dist/index.html not found after build!"; exit 1; } && \ # Remove source maps in production (optional, for smaller size) find dist -name "*.map" -delete && \ # Show build summary echo "✅ Build successful - dist/ contains $(find dist -type f | wc -l) files" && \ du -sh dist/ # Production stage - nginx alpine FROM nginx:1.27-alpine # Install minimal dependencies for healthcheck RUN apk add --no-cache wget && \ rm -rf /var/cache/apk/* # Remove default nginx config RUN rm -rf /etc/nginx/conf.d/default.conf # Copy custom nginx configuration optimized for production COPY nginx.production.conf /etc/nginx/conf.d/default.conf # Copy built assets from builder COPY --from=builder /app/dist /usr/share/nginx/html # Create health check endpoint RUN echo '#!/bin/sh' > /usr/share/nginx/html/health && \ echo 'exit 0' >> /usr/share/nginx/html/health && \ chmod +x /usr/share/nginx/html/health # Set proper permissions RUN chown -R nginx:nginx /usr/share/nginx/html && \ chmod -R 755 /usr/share/nginx/html # Nginx alpine image already runs as non-root user (nginx) # Expose port EXPOSE 80 # Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://localhost/health || exit 1 # Run nginx CMD ["nginx", "-g", "daemon off;"]