Files
Rezepte/DEPLOYMENT.md

301 lines
7.2 KiB
Markdown

# 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 <your-repository-url> /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: ./nodejs-version/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: ./nodejs-version/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
```