diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..7b39846 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,58 @@ +# Docker ignore file for Etsy Finance Tracker +# Excludes unnecessary files from Docker build context + +# Node modules - will be installed in container +node_modules/ +client/node_modules/ +server/node_modules/ + +# Build outputs - will be created in container +client/dist/ +server/dist/ +build/ + +# Development files +.git/ +.gitignore +*.md +LICENSE + +# Environment and config files +.env* +!.env.example + +# Logs +*.log +logs/ + +# Data files - these should be mounted as volumes +data/ +!data/README.md + +# IDE and editor files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS generated files +.DS_Store +.DS_Store? +._* +Thumbs.db +ehthumbs.db + +# Test and coverage +coverage/ +test-results/ +.nyc_output/ + +# Temporary files +tmp/ +temp/ +*.tmp + +# Mac specific +.Spotlight-V100 +.Trashes \ No newline at end of file diff --git a/.gitignore b/.gitignore index de65490..720bab5 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ build/ .env.development.local .env.test.local .env.production.local +server/.env # Logs npm-debug.log* diff --git a/DOCKER_DEPLOYMENT.md b/DOCKER_DEPLOYMENT.md new file mode 100644 index 0000000..932418c --- /dev/null +++ b/DOCKER_DEPLOYMENT.md @@ -0,0 +1,183 @@ +# Docker Deployment Guide for Mac Mini + +This guide will help you deploy the Etsy Finance Tracker on your Mac Mini using Docker. + +## Prerequisites + +1. **Install Docker Desktop** on your Mac Mini: + ```bash + # Option 1: Download from Docker website + # Go to https://docs.docker.com/desktop/mac/install/ + + # Option 2: Install with Homebrew (if available) + brew install --cask docker + ``` + +2. **Install Git** (if not already installed): + ```bash + brew install git + ``` + +## Deployment Steps + +### 1. Clone the Repository +```bash +git clone https://github.com/dlawler489/etsy-finance-tracker.git +cd etsy-finance-tracker +``` + +### 2. Prepare Your Data +```bash +# Create the data directory structure +mkdir -p data/{csv,pdf,spreadsheets} + +# Copy your business files to the data directory +# Example: +# cp ~/Documents/BusinessData/*.csv data/csv/ +# cp ~/Documents/BusinessData/*.pdf data/pdf/ +# cp ~/Documents/BusinessData/*.xlsx data/spreadsheets/ +``` + +### 3. Configure Environment (Optional) +```bash +# Copy the production environment template +cp server/.env.production server/.env + +# Edit the environment file if needed +nano server/.env +``` + +### 4. Build and Run with Docker Compose +```bash +# Build and start the application +docker-compose up --build -d + +# View logs +docker-compose logs -f + +# Check status +docker-compose ps +``` + +### 5. Access Your Application +- **Web Interface**: http://localhost:3000 +- **API Health Check**: http://localhost:3000/health + +## Management Commands + +### Start/Stop the Application +```bash +# Start +docker-compose up -d + +# Stop +docker-compose down + +# Restart +docker-compose restart +``` + +### View Logs +```bash +# All services +docker-compose logs -f + +# Specific service +docker-compose logs -f etsy-tracker +``` + +### Update the Application +```bash +# Pull latest code +git pull origin main + +# Rebuild and restart +docker-compose down +docker-compose up --build -d +``` + +### Backup Your Data +```bash +# Your business data in the data/ directory is automatically persisted +# To backup: +tar -czf etsy-tracker-backup-$(date +%Y%m%d).tar.gz data/ +``` + +## Troubleshooting + +### Check Application Health +```bash +# Test the health endpoint +curl http://localhost:3000/health + +# Check container logs +docker-compose logs etsy-tracker +``` + +### Common Issues + +1. **Port Already in Use**: + ```bash + # Change port in docker-compose.yml + ports: + - "3001:3000" # Change 3000 to 3001 + ``` + +2. **Permission Issues**: + ```bash + # Fix data directory permissions + sudo chown -R $(whoami):$(whoami) data/ + ``` + +3. **Memory Issues**: + ```bash + # Add memory limits to docker-compose.yml + deploy: + resources: + limits: + memory: 512M + ``` + +## File Structure + +Your deployment will look like this: +``` +etsy-finance-tracker/ +├── data/ # Your business data (persistent) +│ ├── csv/ # CSV files +│ ├── pdf/ # PDF documents +│ └── spreadsheets/ # Excel files +├── docker-compose.yml # Container orchestration +├── Dockerfile # Container configuration +└── ... (application code) +``` + +## Security Notes + +- The `data/` directory contains your sensitive business files +- This directory is mounted as a volume and persists between container restarts +- Never commit the `data/` directory to git +- Change default passwords in `.env` file for production use + +## Performance Optimization + +For better performance on Mac Mini: + +1. **Allocate more resources to Docker Desktop**: + - Open Docker Desktop preferences + - Go to Resources → Advanced + - Increase Memory to at least 4GB + - Increase CPU to at least 2 cores + +2. **Enable BuildKit** for faster builds: + ```bash + export DOCKER_BUILDKIT=1 + ``` + +## Support + +If you encounter issues: +1. Check the logs: `docker-compose logs` +2. Verify Docker is running: `docker version` +3. Check port availability: `lsof -i :3000` +4. Review the troubleshooting section above \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bc6ad66 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,61 @@ +# Multi-stage build for production-ready Etsy Finance Tracker + +# 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 runtime +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/ + +# Copy built client +COPY --from=client-build --chown=nodejs:nodejs /app/client/dist ./client/dist/ + +# Create data directory for persistent storage +RUN mkdir -p /app/data && chown nodejs:nodejs /app/data + +# Switch to non-root user +USER nodejs + +# Expose port +EXPOSE 3000 + +# Health check +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD curl -f http://localhost:3000/health || exit 1 + +# Start the application +ENTRYPOINT ["dumb-init", "--"] +CMD ["node", "server/index.js"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..d207dba --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,51 @@ +version: '3.8' + +services: + # Etsy Finance Tracker Application + etsy-tracker: + build: + context: . + dockerfile: Dockerfile + container_name: etsy-finance-tracker + ports: + - "3000:3000" + environment: + - NODE_ENV=production + - PORT=3000 + volumes: + # Mount data directory for persistent storage + - ./data:/app/data + # Optional: Mount uploads directory if needed + - etsy_uploads:/app/uploads + restart: unless-stopped + networks: + - etsy-network + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:3000/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + # Optional: MongoDB for future database needs + # mongodb: + # image: mongo:6.0 + # container_name: etsy-mongo + # ports: + # - "27017:27017" + # environment: + # MONGO_INITDB_ROOT_USERNAME: admin + # MONGO_INITDB_ROOT_PASSWORD: changeme + # volumes: + # - etsy_mongodb_data:/data/db + # networks: + # - etsy-network + # restart: unless-stopped + +volumes: + etsy_uploads: + # etsy_mongodb_data: + +networks: + etsy-network: + driver: bridge \ No newline at end of file diff --git a/server/.env.production b/server/.env.production new file mode 100644 index 0000000..e575a7f --- /dev/null +++ b/server/.env.production @@ -0,0 +1,34 @@ +# Production Environment Configuration +# Copy this file to .env and customize for your deployment + +# Application +NODE_ENV=production +PORT=3000 + +# Client Configuration +CLIENT_URL=http://localhost:3000 + +# Database (when using MongoDB) +# MONGODB_URI=mongodb://mongodb:27017/etsy-tracker +# DB_NAME=etsy-tracker + +# JWT Configuration +JWT_SECRET=your-super-secret-jwt-key-change-this-in-production +JWT_EXPIRES_IN=7d + +# CORS Configuration +ALLOWED_ORIGINS=http://localhost:3000,http://127.0.0.1:3000 + +# File Upload Limits +MAX_FILE_SIZE=10mb +UPLOAD_PATH=/app/uploads + +# Logging +LOG_LEVEL=info + +# Rate Limiting +RATE_LIMIT_WINDOW_MS=900000 +RATE_LIMIT_MAX_REQUESTS=100 + +# Security +BCRYPT_SALT_ROUNDS=12 \ No newline at end of file diff --git a/server/src/index.ts b/server/src/index.ts index daf3e6d..9b80832 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -44,6 +44,16 @@ app.use(express.urlencoded({ extended: true })); // Logging middleware app.use(morgan('combined')); +// Health check endpoint for Docker +app.get('/health', (req, res) => { + res.status(200).json({ + status: 'OK', + timestamp: new Date().toISOString(), + uptime: process.uptime(), + service: 'Etsy Finance Tracker API' + }); +}); + // Database connection (temporarily disabled for development) // mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost:27017/etsy-tracker') // .then(() => console.log('Connected to MongoDB'))