# Deployment auf externem Server ## Voraussetzungen auf dem Server - Docker und Docker Compose installiert - Git installiert - Port 80 und/oder 443 für Web-Traffic geöffnet - Optional: Reverse Proxy (nginx/Apache) für SSL-Termination ## 1. Repository auf Server klonen ```bash git clone /opt/rezepte cd /opt/rezepte ``` ## 2. Produktions-Umgebung konfigurieren ### Environment-Datei erstellen ```bash cp .env.example .env.production ``` ### .env.production anpassen: ```env # Database DATABASE_URL="mysql://rezepte_user:secure_password_here@mysql:3306/rezepte" # Security JWT_SECRET="your-super-secure-jwt-secret-min-32-chars" # CORS - Ihre Domain(s) eintragen CORS_ORIGIN="https://yourdomain.com" # Environment NODE_ENV=production # Uploads UPLOAD_DIR=/app/uploads MAX_UPLOAD_SIZE=10mb # Server PORT=3001 ``` ## 3. Docker Compose für Produktion anpassen ### docker-compose.production.yml erstellen: ```yaml version: '3.8' services: mysql: image: mysql:8.0 container_name: rezepte-mysql-prod restart: unless-stopped environment: MYSQL_DATABASE: rezepte MYSQL_USER: rezepte_user MYSQL_PASSWORD: secure_password_here MYSQL_ROOT_PASSWORD: super_secure_root_password volumes: - mysql_data:/var/lib/mysql - ./Rezepte.sql:/docker-entrypoint-initdb.d/01-rezepte.sql:ro - ./ingredients.sql:/docker-entrypoint-initdb.d/02-ingredients.sql:ro - ./Zubereitung.sql:/docker-entrypoint-initdb.d/03-zubereitung.sql:ro - ./rezepte_bilder.sql:/docker-entrypoint-initdb.d/04-bilder.sql:ro healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] timeout: 20s retries: 10 networks: - rezepte-network backend: build: context: ./backend dockerfile: Dockerfile container_name: rezepte-backend-prod restart: unless-stopped environment: - NODE_ENV=production - DATABASE_URL=mysql://rezepte_user:secure_password_here@mysql:3306/rezepte - JWT_SECRET=your-super-secure-jwt-secret-min-32-chars - CORS_ORIGIN=https://yourdomain.com - PORT=3001 volumes: - uploads_data:/app/uploads - ./upload:/app/legacy-uploads:ro depends_on: mysql: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3001/api/health"] interval: 30s timeout: 10s retries: 3 networks: - rezepte-network frontend: build: context: ./frontend dockerfile: Dockerfile args: - VITE_API_BASE_URL=https://yourdomain.com/api container_name: rezepte-frontend-prod restart: unless-stopped ports: - "80:80" - "443:443" # Wenn SSL direkt im Container volumes: - ./ssl:/etc/nginx/ssl:ro # SSL-Zertifikate depends_on: - backend healthcheck: test: ["CMD", "curl", "-f", "http://localhost/"] interval: 30s timeout: 10s retries: 3 networks: - rezepte-network volumes: mysql_data: driver: local uploads_data: driver: local networks: rezepte-network: driver: bridge ``` ## 4. SSL/HTTPS einrichten ### Option A: Let's Encrypt mit Certbot ```bash # Certbot installieren sudo apt update sudo apt install certbot # SSL-Zertifikat erstellen sudo certbot certonly --standalone -d yourdomain.com # Zertifikate kopieren sudo cp /etc/letsencrypt/live/yourdomain.com/fullchain.pem ./ssl/ sudo cp /etc/letsencrypt/live/yourdomain.com/privkey.pem ./ssl/ ``` ### Option B: Reverse Proxy (empfohlen) ```nginx # /etc/nginx/sites-available/rezepte server { listen 80; server_name yourdomain.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name yourdomain.com; ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem; location / { proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location /api/ { proxy_pass http://localhost:3001; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location /uploads/ { proxy_pass http://localhost:3001; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } ``` ## 5. Deployment-Skripte ### deploy.sh erstellen: ```bash #!/bin/bash set -e echo "🚀 Deploying Rezepte..." # Git pull latest changes git pull origin main # Build and start containers docker-compose -f docker-compose.production.yml down docker-compose -f docker-compose.production.yml up --build -d # Health check echo "⏳ Waiting for services to start..." sleep 30 # Check if all services are healthy if docker-compose -f docker-compose.production.yml ps | grep -q "Up (healthy)"; then echo "✅ Deployment successful!" echo "🌐 Application available at: https://yourdomain.com" else echo "❌ Deployment failed! Check logs:" docker-compose -f docker-compose.production.yml logs exit 1 fi ``` ### backup.sh erstellen: ```bash #!/bin/bash DATE=$(date +%Y%m%d_%H%M%S) BACKUP_DIR="/opt/backups/rezepte" mkdir -p $BACKUP_DIR # Database backup docker exec rezepte-mysql-prod mysqldump -u root -psuper_secure_root_password rezepte > $BACKUP_DIR/database_$DATE.sql # Uploads backup docker cp rezepte-backend-prod:/app/uploads $BACKUP_DIR/uploads_$DATE # Keep only last 7 backups find $BACKUP_DIR -name "database_*.sql" -mtime +7 -delete find $BACKUP_DIR -name "uploads_*" -mtime +7 -exec rm -rf {} + echo "✅ Backup completed: $BACKUP_DIR" ``` ## 6. Monitoring und Logs ### Logs anzeigen: ```bash # Alle Services docker-compose -f docker-compose.production.yml logs -f # Nur Backend docker-compose -f docker-compose.production.yml logs -f backend # Nur Frontend docker-compose -f docker-compose.production.yml logs -f frontend ``` ### Service-Status prüfen: ```bash docker-compose -f docker-compose.production.yml ps ``` ## 7. Automatische Updates (Optional) ### Crontab für automatische Backups: ```bash # Täglich um 2 Uhr 0 2 * * * /opt/rezepte/backup.sh # Wöchentlich SSL-Zertifikat erneuern 0 3 * * 0 certbot renew --quiet && systemctl reload nginx ``` ## 8. Sicherheitshinweise 1. **Firewall konfigurieren**: Nur Ports 22 (SSH), 80 (HTTP), 443 (HTTPS) öffnen 2. **SSH-Key verwenden**: Passwort-Login deaktivieren 3. **Regelmäßige Updates**: System und Docker regelmäßig aktualisieren 4. **Backup-Strategie**: Automatische Backups einrichten 5. **Monitoring**: Log-Monitoring und Alerting einrichten ## Troubleshooting ### Container startet nicht: ```bash docker-compose -f docker-compose.production.yml logs [service-name] ``` ### Database-Probleme: ```bash # In MySQL-Container einloggen docker exec -it rezepte-mysql-prod mysql -u root -p # Database-Status prüfen SHOW DATABASES; USE rezepte; SHOW TABLES; ``` ### Permission-Probleme: ```bash # Upload-Ordner Permissions docker exec -it rezepte-backend-prod chown -R backend:nodejs /app/uploads ```