From f7dc75d514a087d473aacb880673bccb600b74d8 Mon Sep 17 00:00:00 2001 From: Oliver Gwyther Date: Fri, 15 Aug 2025 20:40:39 +0100 Subject: [PATCH] Enhance Docker setup by updating .dockerignore to include additional files and directories, modifying docker-compose.yml to add build arguments and Traefik labels, and improving the Dockerfile with build-time environment variables, health checks, and permission settings for security. --- .dockerignore | 105 ++++++++++++++------- DOCKER.md | 224 +++++++++++++++++++++++++++++++++++++++++++++ Dockerfile | 41 ++++++++- docker-compose.yml | 11 ++- 4 files changed, 340 insertions(+), 41 deletions(-) create mode 100644 DOCKER.md diff --git a/.dockerignore b/.dockerignore index 52bb310..c58322e 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,47 +1,82 @@ +# Node modules node_modules -npm-debug.log -.git -.gitignore -README.md +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Build outputs +dist +build + +# Environment files .env .env.local .env.development.local .env.test.local .env.production.local -.nyc_output -coverage -.nyc_output -.coverage -coverage.json -*.lcov -.DS_Store -Thumbs.db -*.log + +# Git +.git +.gitignore + +# IDE files .vscode .idea *.swp *.swo -*~ -dist -build -.cache -.parcel-cache -.next -.nuxt -.vuepress/dist -.serverless -.fusebox/ -.dynamodb/ -.tern-port -.vscode-test -.yarn/cache -.yarn/unplugged -.yarn/build-state.yml -.yarn/install-state.gz -.pnp.* -scripts -drizzle -oliver-super-admin.json -setup-oliver-admin.html + +# OS files +.DS_Store +Thumbs.db + +# Logs logs *.log + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Coverage directory used by tools like istanbul +coverage + +# Dependency directories +.npm +.eslintcache + +# Optional npm cache directory +.npm + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# Development files +*.md +LICENSE +docs/ +examples/ +test/ +tests/ +spec/ +.github/ + +# Docker files (don't copy into container) +Dockerfile* +docker-compose*.yml +.dockerignore + +# Database files +*.db +*.sqlite + +# Temporary files +tmp/ +temp/ \ No newline at end of file diff --git a/DOCKER.md b/DOCKER.md new file mode 100644 index 0000000..9ab4c48 --- /dev/null +++ b/DOCKER.md @@ -0,0 +1,224 @@ +# Docker Setup for ScriptShare + +This document explains how to build and run ScriptShare using Docker. + +## Prerequisites + +- Docker Desktop (for Windows/macOS) or Docker Engine (for Linux) +- Docker Compose (usually included with Docker Desktop) + +## Quick Start + +### Using Docker Compose (Recommended) + +```bash +# Clone the repository +git clone +cd scriptshare-cursor + +# Build and start the application +docker-compose up --build + +# Access the application at http://localhost:3000 +``` + +### Using Docker Build Directly + +```bash +# Build the image +docker build -t scriptshare . + +# Run the container +docker run -p 3000:80 scriptshare +``` + +## Configuration + +### Build Arguments + +You can customize the build using these arguments: + +```bash +docker build \ + --build-arg VITE_APP_NAME="Your ScriptShare" \ + --build-arg VITE_APP_URL="https://your-domain.com" \ + --build-arg VITE_ANALYTICS_ENABLED="true" \ + -t scriptshare . +``` + +### Environment Variables + +| Variable | Default | Description | +|----------|---------|-------------| +| `VITE_APP_NAME` | "ScriptShare" | Application name shown in UI | +| `VITE_APP_URL` | "https://scriptshare.example.com" | Base URL for the application | +| `VITE_ANALYTICS_ENABLED` | "false" | Enable/disable analytics tracking | + +### Docker Compose Configuration + +Update `docker-compose.yml` to customize build arguments: + +```yaml +services: + scriptshare: + build: + context: . + dockerfile: Dockerfile + args: + - VITE_APP_NAME=Your ScriptShare + - VITE_APP_URL=https://your-domain.com + - VITE_ANALYTICS_ENABLED=true + ports: + - "3000:80" +``` + +## Features + +### Multi-Stage Build + +The Dockerfile uses a multi-stage build for optimization: + +1. **Builder Stage**: Builds the React application with all dependencies +2. **Production Stage**: Serves the built files using nginx + +### Security Features + +- Runs as non-root user (nginx) +- Minimal production image based on nginx:alpine +- Proper file permissions +- Health checks included + +### Dependencies Handled + +The build process properly handles: +- Native modules (bcrypt, etc.) with build dependencies +- React Syntax Highlighter +- All UI component libraries +- TypeScript compilation + +### Health Checks + +The container includes health checks at: +- Docker level: `curl -f http://localhost/health` +- nginx level: Configured in nginx.conf + +## Development + +### Development Build + +For development with hot reloading: + +```bash +# Install dependencies locally +npm install + +# Start development server +npm run dev + +# Access at http://localhost:5173 +``` + +### Building for Production + +```bash +# Build the application +npm run build + +# Preview the build +npm run preview +``` + +## Production Deployment + +### With Reverse Proxy (Recommended) + +If using with a reverse proxy like Traefik or nginx: + +```yaml +# docker-compose.yml +services: + scriptshare: + build: . + labels: + - "traefik.enable=true" + - "traefik.http.routers.scriptshare.rule=Host(\`your-domain.com\`)" + - "traefik.http.services.scriptshare.loadbalancer.server.port=80" +``` + +### Standalone Deployment + +```bash +# Build for production +docker build -t scriptshare:latest . + +# Run with custom port +docker run -d -p 80:80 --name scriptshare-app scriptshare:latest +``` + +## Volumes + +The container uses these volumes: + +- `scriptshare_logs:/var/log/nginx` - nginx logs + +## Troubleshooting + +### Build Issues + +1. **Native dependency errors**: Ensure Docker has enough memory allocated +2. **Build timeout**: Increase Docker build timeout in Docker Desktop settings +3. **Permission errors**: Check that Docker has access to the project directory + +### Runtime Issues + +1. **Health check failures**: Check nginx logs in the container +2. **Static files not served**: Verify build output in `/usr/share/nginx/html` +3. **Environment variables**: Ensure they're set at build time, not runtime + +### Checking Logs + +```bash +# View application logs +docker-compose logs scriptshare + +# View nginx access logs +docker exec tail -f /var/log/nginx/access.log + +# View nginx error logs +docker exec tail -f /var/log/nginx/error.log +``` + +## Image Size Optimization + +The production image is optimized by: + +- Using Alpine Linux base images +- Multi-stage builds to exclude build dependencies +- .dockerignore to exclude unnecessary files +- Only copying built assets to production stage + +Expected image size: ~25-30MB (compressed) + +## Security Considerations + +- Container runs as non-root user +- Minimal attack surface with alpine base +- No build tools in production image +- Proper file permissions set +- Health checks for monitoring + +## Updates + +To update the application: + +1. Pull latest code changes +2. Rebuild the image: `docker-compose build` +3. Restart containers: `docker-compose up -d` + +## Support + +For issues with Docker setup: +1. Check Docker Desktop is running +2. Verify Docker version compatibility +3. Review build logs for specific errors +4. Check system resources (memory, disk space) diff --git a/Dockerfile b/Dockerfile index 1ff9155..90f45db 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,31 +1,66 @@ # Build stage FROM node:18-alpine AS builder +# Install build dependencies for native modules (bcrypt, etc.) +RUN apk add --no-cache python3 make g++ libc6-compat + WORKDIR /app -# Copy package files +# Copy package files first for better Docker layer caching COPY package*.json ./ -# Install ALL dependencies (including dev dependencies needed for build) -RUN npm ci +# Install dependencies with proper npm cache handling +RUN npm ci --only=production=false --silent # Copy source code COPY . . +# Set build-time environment variables +ARG VITE_APP_NAME="ScriptShare" +ARG VITE_APP_URL="https://scriptshare.example.com" +ARG VITE_ANALYTICS_ENABLED="false" + +# Export as environment variables for Vite build +ENV VITE_APP_NAME=$VITE_APP_NAME +ENV VITE_APP_URL=$VITE_APP_URL +ENV VITE_ANALYTICS_ENABLED=$VITE_ANALYTICS_ENABLED + # Build the application RUN npm run build +# Verify build output exists +RUN ls -la /app/dist + # Production stage FROM nginx:alpine +# Install curl for health checks +RUN apk add --no-cache curl + # Copy built files from builder stage COPY --from=builder /app/dist /usr/share/nginx/html # Copy nginx configuration COPY nginx.conf /etc/nginx/nginx.conf +# Create nginx pid directory +RUN mkdir -p /var/run/nginx + +# Set proper permissions +RUN chown -R nginx:nginx /usr/share/nginx/html +RUN chown -R nginx:nginx /var/cache/nginx +RUN chown -R nginx:nginx /var/log/nginx +RUN chown -R nginx:nginx /var/run/nginx + +# Switch to non-root user for security +USER nginx + # Expose port 80 EXPOSE 80 +# Add healthcheck +HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ + CMD curl -f http://localhost/health || exit 1 + # Start nginx CMD ["nginx", "-g", "daemon off;"] diff --git a/docker-compose.yml b/docker-compose.yml index 6ca98af..4dc90cc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,13 +5,16 @@ services: build: context: . dockerfile: Dockerfile + args: + - VITE_APP_NAME=ScriptShare + - VITE_APP_URL=http://localhost:3000 + - VITE_ANALYTICS_ENABLED=false ports: - "3000:80" environment: - NODE_ENV=production restart: unless-stopped volumes: - - scriptshare_data:/usr/share/nginx/html - scriptshare_logs:/var/log/nginx healthcheck: test: ["CMD", "curl", "-f", "http://localhost/health"] @@ -19,9 +22,11 @@ services: timeout: 10s retries: 3 start_period: 40s + labels: + - "traefik.enable=true" + - "traefik.http.routers.scriptshare.rule=Host(`scriptshare.localhost`)" + - "traefik.http.services.scriptshare.loadbalancer.server.port=80" volumes: - scriptshare_data: - driver: local scriptshare_logs: driver: local