You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							170 lines
						
					
					
						
							5.2 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							170 lines
						
					
					
						
							5.2 KiB
						
					
					
				
								# TimeSafari Docker Build
							 | 
						|
								# Author: Matthew Raymer
							 | 
						|
								# Description: Multi-stage Docker build for TimeSafari web application
							 | 
						|
								# 
							 | 
						|
								# Build Process:
							 | 
						|
								# 1. Base stage: Node.js with build dependencies
							 | 
						|
								# 2. Builder stage: Copy pre-built web assets from host
							 | 
						|
								# 3. Production stage: Nginx server with optimized assets
							 | 
						|
								# 
							 | 
						|
								# Note: Web assets are built on the host using npm scripts before Docker build
							 | 
						|
								#
							 | 
						|
								# Security Features:
							 | 
						|
								# - Non-root user execution
							 | 
						|
								# - Minimal attack surface with Alpine Linux
							 | 
						|
								# - Multi-stage build to reduce image size
							 | 
						|
								# - No build dependencies in final image
							 | 
						|
								#
							 | 
						|
								# Usage:
							 | 
						|
								#   IMPORTANT: Build web assets first, then build Docker image
							 | 
						|
								#   
							 | 
						|
								#   Using npm scripts (recommended):
							 | 
						|
								#   Production: npm run build:web:docker:prod
							 | 
						|
								#   Test: npm run build:web:docker:test
							 | 
						|
								#   Development: npm run build:web:docker
							 | 
						|
								#   
							 | 
						|
								#   Manual workflow:
							 | 
						|
								#   1. Build web assets: npm run build:web:build -- --mode production
							 | 
						|
								#   2. Build Docker: docker build -t timesafari:latest .
							 | 
						|
								#   
							 | 
						|
								#   Note: For development, use npm run build:web directly (no Docker needed)
							 | 
						|
								#
							 | 
						|
								# Build Arguments:
							 | 
						|
								#   BUILD_MODE: development, test, or production (default: production)
							 | 
						|
								#   NODE_ENV: node environment (default: production)
							 | 
						|
								#
							 | 
						|
								# Environment Variables:
							 | 
						|
								#   NODE_ENV: Build environment (development/production)
							 | 
						|
								#   BUILD_MODE: Build mode for asset selection (development/test/production)
							 | 
						|
								#
							 | 
						|
								# Build Context:
							 | 
						|
								#   This Dockerfile is designed to work when the build context is set to
							 | 
						|
								#   ./crowd-funder-for-time-pwa from the parent directory (where docker-compose.yml is located)
							 | 
						|
								
							 | 
						|
								# =============================================================================
							 | 
						|
								# BASE STAGE - Common dependencies and setup
							 | 
						|
								# =============================================================================
							 | 
						|
								FROM node:22-alpine3.20 AS base
							 | 
						|
								
							 | 
						|
								# Install system dependencies for build process
							 | 
						|
								RUN apk add --no-cache \
							 | 
						|
								    bash \
							 | 
						|
								    git \
							 | 
						|
								    python3 \
							 | 
						|
								    py3-pip \
							 | 
						|
								    py3-setuptools \
							 | 
						|
								    make \
							 | 
						|
								    g++ \
							 | 
						|
								    gcc \
							 | 
						|
								    && rm -rf /var/cache/apk/*
							 | 
						|
								
							 | 
						|
								# Create non-root user for security
							 | 
						|
								RUN addgroup -g 1001 -S nodejs && \
							 | 
						|
								    adduser -S nextjs -u 1001
							 | 
						|
								
							 | 
						|
								# Set working directory
							 | 
						|
								WORKDIR /app
							 | 
						|
								
							 | 
						|
								# Copy package files for dependency installation
							 | 
						|
								# Note: These files are in the project root (crowd-funder-for-time-pwa directory)
							 | 
						|
								COPY package*.json ./
							 | 
						|
								
							 | 
						|
								# Install dependencies with security audit
							 | 
						|
								RUN npm ci --only=production --audit --fund=false && \
							 | 
						|
								    npm audit fix --audit-level=moderate || true
							 | 
						|
								
							 | 
						|
								# =============================================================================
							 | 
						|
								# BUILDER STAGE - Copy pre-built assets
							 | 
						|
								# =============================================================================
							 | 
						|
								FROM base AS builder
							 | 
						|
								
							 | 
						|
								# Define build arguments with defaults
							 | 
						|
								ARG BUILD_MODE=production
							 | 
						|
								ARG NODE_ENV=production
							 | 
						|
								
							 | 
						|
								# Set environment variables from build arguments
							 | 
						|
								ENV BUILD_MODE=${BUILD_MODE}
							 | 
						|
								ENV NODE_ENV=${NODE_ENV}
							 | 
						|
								
							 | 
						|
								# Copy pre-built assets from host
							 | 
						|
								# Note: dist/ directory is in the project root (crowd-funder-for-time-pwa directory)
							 | 
						|
								COPY dist/ ./dist/
							 | 
						|
								
							 | 
						|
								# Verify build output exists
							 | 
						|
								RUN ls -la dist/ || (echo "Build output not found in dist/ directory" && exit 1)
							 | 
						|
								
							 | 
						|
								# =============================================================================
							 | 
						|
								# PRODUCTION STAGE - Nginx server
							 | 
						|
								# =============================================================================
							 | 
						|
								FROM nginx:alpine AS production
							 | 
						|
								
							 | 
						|
								# Define build arguments for production stage
							 | 
						|
								ARG BUILD_MODE=production
							 | 
						|
								ARG NODE_ENV=production
							 | 
						|
								
							 | 
						|
								# Set environment variables
							 | 
						|
								ENV BUILD_MODE=${BUILD_MODE}
							 | 
						|
								ENV NODE_ENV=${NODE_ENV}
							 | 
						|
								
							 | 
						|
								# Install security updates and clean cache
							 | 
						|
								RUN apk update && \
							 | 
						|
								    apk upgrade && \
							 | 
						|
								    apk add --no-cache \
							 | 
						|
								    curl \
							 | 
						|
								    && rm -rf /var/cache/apk/*
							 | 
						|
								
							 | 
						|
								# Use existing nginx user from base image (nginx user and group already exist)
							 | 
						|
								# No need to create new user as nginx:alpine already has nginx user
							 | 
						|
								
							 | 
						|
								# Copy main nginx configuration
							 | 
						|
								COPY docker/nginx.conf /etc/nginx/nginx.conf
							 | 
						|
								
							 | 
						|
								# Copy production nginx configuration
							 | 
						|
								COPY docker/default.conf /etc/nginx/conf.d/default.conf
							 | 
						|
								
							 | 
						|
								# Copy built assets from builder stage
							 | 
						|
								COPY --from=builder --chown=nginx:nginx /app/dist /usr/share/nginx/html
							 | 
						|
								
							 | 
						|
								# Create necessary directories with proper permissions
							 | 
						|
								RUN mkdir -p /var/cache/nginx /var/log/nginx /tmp && \
							 | 
						|
								    chown -R nginx:nginx /var/cache/nginx /var/log/nginx /tmp && \
							 | 
						|
								    chown -R nginx:nginx /usr/share/nginx/html
							 | 
						|
								
							 | 
						|
								# Switch to non-root user
							 | 
						|
								USER nginx
							 | 
						|
								
							 | 
						|
								# Expose port 80
							 | 
						|
								EXPOSE 80
							 | 
						|
								
							 | 
						|
								# Health check
							 | 
						|
								HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
							 | 
						|
								    CMD curl -f http://localhost/ || exit 1
							 | 
						|
								
							 | 
						|
								# Start nginx with proper signal handling
							 | 
						|
								CMD ["nginx", "-g", "daemon off;"]
							 | 
						|
								
							 | 
						|
								# =============================================================================
							 | 
						|
								# TEST STAGE - For test environment testing
							 | 
						|
								# =============================================================================
							 | 
						|
								FROM production AS test
							 | 
						|
								
							 | 
						|
								# Define build arguments for test stage
							 | 
						|
								ARG BUILD_MODE=test
							 | 
						|
								ARG NODE_ENV=test
							 | 
						|
								
							 | 
						|
								# Set environment variables
							 | 
						|
								ENV BUILD_MODE=${BUILD_MODE}
							 | 
						|
								ENV NODE_ENV=${NODE_ENV}
							 | 
						|
								
							 | 
						|
								# Copy test-specific nginx configuration
							 | 
						|
								COPY docker/staging.conf /etc/nginx/conf.d/default.conf
							 | 
						|
								
							 | 
						|
								# Expose port 80
							 | 
						|
								EXPOSE 80
							 | 
						|
								
							 | 
						|
								# Health check for staging
							 | 
						|
								HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
							 | 
						|
								    CMD curl -f http://localhost/health || exit 1
							 | 
						|
								
							 | 
						|
								# Start nginx
							 | 
						|
								CMD ["nginx", "-g", "daemon off;"] 
							 |