643 lines
13 KiB
Markdown
643 lines
13 KiB
Markdown
# 🚀 Deployment
|
||
|
||
Anleitung für das Deployment des Ninja Cross Parkour Systems in verschiedenen Umgebungen.
|
||
|
||
## 📋 Inhaltsverzeichnis
|
||
|
||
- [🏗️ Deployment-Übersicht](#️-deployment-übersicht)
|
||
- [🔧 Vorbereitung](#-vorbereitung)
|
||
- [🐳 Docker-Deployment](#-docker-deployment)
|
||
- [☁️ Cloud-Deployment](#️-cloud-deployment)
|
||
- [🖥️ VPS-Deployment](#️-vps-deployment)
|
||
- [🔧 Konfiguration](#-konfiguration)
|
||
- [📊 Monitoring](#-monitoring)
|
||
- [🔄 CI/CD](#-cicd)
|
||
|
||
## 🏗️ Deployment-Übersicht
|
||
|
||
### Deployment-Optionen
|
||
- **Docker** - Containerisierte Bereitstellung
|
||
- **Cloud** - AWS, Azure, Google Cloud
|
||
- **VPS** - Virtuelle private Server
|
||
- **On-Premise** - Lokale Server
|
||
|
||
### System-Anforderungen
|
||
- **CPU:** 2+ Kerne
|
||
- **RAM:** 4+ GB
|
||
- **Storage:** 50+ GB SSD
|
||
- **Network:** 100+ Mbps
|
||
|
||
## 🔧 Vorbereitung
|
||
|
||
### Code vorbereiten
|
||
```bash
|
||
# Repository klonen
|
||
git clone <repository-url>
|
||
cd ninjaserver
|
||
|
||
# Abhängigkeiten installieren
|
||
npm install
|
||
|
||
# Produktions-Build erstellen
|
||
npm run build
|
||
|
||
# Tests ausführen
|
||
npm test
|
||
```
|
||
|
||
### Umgebungsvariablen
|
||
```bash
|
||
# .env.production erstellen
|
||
cp .env.example .env.production
|
||
|
||
# Produktionswerte setzen
|
||
NODE_ENV=production
|
||
PORT=3000
|
||
DB_HOST=production-db-host
|
||
DB_PORT=5432
|
||
DB_NAME=ninjaserver
|
||
DB_USER=ninja_user
|
||
DB_PASSWORD=secure_password
|
||
JWT_SECRET=your_jwt_secret_here
|
||
SESSION_SECRET=your_session_secret_here
|
||
```
|
||
|
||
### Datenbank vorbereiten
|
||
```sql
|
||
-- Produktionsdatenbank erstellen
|
||
CREATE DATABASE ninjaserver;
|
||
CREATE USER ninja_user WITH PASSWORD 'secure_password';
|
||
GRANT ALL PRIVILEGES ON DATABASE ninjaserver TO ninja_user;
|
||
|
||
-- Schema initialisieren
|
||
\c ninjaserver
|
||
\i scripts/init-db.sql
|
||
```
|
||
|
||
## 🐳 Docker-Deployment
|
||
|
||
### Dockerfile
|
||
```dockerfile
|
||
# Multi-stage build
|
||
FROM node:18-alpine AS builder
|
||
|
||
WORKDIR /app
|
||
COPY package*.json ./
|
||
RUN npm ci --only=production
|
||
|
||
FROM node:18-alpine AS runtime
|
||
|
||
# Sicherheitsupdates
|
||
RUN apk update && apk upgrade
|
||
|
||
# Nicht-root Benutzer erstellen
|
||
RUN addgroup -g 1001 -S nodejs
|
||
RUN adduser -S ninja -u 1001
|
||
|
||
WORKDIR /app
|
||
|
||
# Abhängigkeiten kopieren
|
||
COPY --from=builder /app/node_modules ./node_modules
|
||
COPY . .
|
||
|
||
# Berechtigungen setzen
|
||
RUN chown -R ninja:nodejs /app
|
||
USER ninja
|
||
|
||
# Port freigeben
|
||
EXPOSE 3000
|
||
|
||
# Health Check
|
||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||
CMD curl -f http://localhost:3000/health || exit 1
|
||
|
||
# Anwendung starten
|
||
CMD ["npm", "start"]
|
||
```
|
||
|
||
### Docker Compose
|
||
```yaml
|
||
version: '3.8'
|
||
|
||
services:
|
||
app:
|
||
build: .
|
||
ports:
|
||
- "3000:3000"
|
||
environment:
|
||
- NODE_ENV=production
|
||
- DB_HOST=postgres
|
||
- DB_PORT=5432
|
||
- DB_NAME=ninjaserver
|
||
- DB_USER=ninja_user
|
||
- DB_PASSWORD=secure_password
|
||
depends_on:
|
||
- postgres
|
||
- redis
|
||
volumes:
|
||
- ./logs:/app/logs
|
||
restart: unless-stopped
|
||
|
||
postgres:
|
||
image: postgres:15-alpine
|
||
environment:
|
||
- POSTGRES_DB=ninjaserver
|
||
- POSTGRES_USER=ninja_user
|
||
- POSTGRES_PASSWORD=secure_password
|
||
volumes:
|
||
- postgres_data:/var/lib/postgresql/data
|
||
- ./scripts/init-db.sql:/docker-entrypoint-initdb.d/init-db.sql
|
||
ports:
|
||
- "5432:5432"
|
||
restart: unless-stopped
|
||
|
||
redis:
|
||
image: redis:7-alpine
|
||
ports:
|
||
- "6379:6379"
|
||
volumes:
|
||
- redis_data:/data
|
||
restart: unless-stopped
|
||
|
||
nginx:
|
||
image: nginx:alpine
|
||
ports:
|
||
- "80:80"
|
||
- "443:443"
|
||
volumes:
|
||
- ./nginx.conf:/etc/nginx/nginx.conf
|
||
- ./ssl:/etc/nginx/ssl
|
||
depends_on:
|
||
- app
|
||
restart: unless-stopped
|
||
|
||
volumes:
|
||
postgres_data:
|
||
redis_data:
|
||
```
|
||
|
||
### Deployment-Skript
|
||
```bash
|
||
#!/bin/bash
|
||
# deploy.sh
|
||
|
||
set -e
|
||
|
||
echo "🚀 Starting deployment..."
|
||
|
||
# Docker Images bauen
|
||
echo "📦 Building Docker images..."
|
||
docker-compose build
|
||
|
||
# Alte Container stoppen
|
||
echo "🛑 Stopping old containers..."
|
||
docker-compose down
|
||
|
||
# Neue Container starten
|
||
echo "▶️ Starting new containers..."
|
||
docker-compose up -d
|
||
|
||
# Health Check
|
||
echo "🔍 Checking health..."
|
||
sleep 30
|
||
curl -f http://localhost:3000/health || exit 1
|
||
|
||
echo "✅ Deployment completed successfully!"
|
||
```
|
||
|
||
## ☁️ Cloud-Deployment
|
||
|
||
### AWS Deployment
|
||
|
||
#### EC2-Instanz
|
||
```bash
|
||
# EC2-Instanz starten
|
||
aws ec2 run-instances \
|
||
--image-id ami-0c02fb55956c7d316 \
|
||
--instance-type t3.medium \
|
||
--key-name ninja-key \
|
||
--security-groups ninja-sg \
|
||
--user-data file://user-data.sh
|
||
```
|
||
|
||
#### RDS-Datenbank
|
||
```bash
|
||
# RDS-Instanz erstellen
|
||
aws rds create-db-instance \
|
||
--db-instance-identifier ninja-db \
|
||
--db-instance-class db.t3.micro \
|
||
--engine postgres \
|
||
--master-username ninja_user \
|
||
--master-user-password secure_password \
|
||
--allocated-storage 20
|
||
```
|
||
|
||
#### Load Balancer
|
||
```bash
|
||
# Application Load Balancer erstellen
|
||
aws elbv2 create-load-balancer \
|
||
--name ninja-alb \
|
||
--subnets subnet-12345 subnet-67890 \
|
||
--security-groups sg-12345
|
||
```
|
||
|
||
### Azure Deployment
|
||
|
||
#### App Service
|
||
```bash
|
||
# App Service erstellen
|
||
az webapp create \
|
||
--resource-group ninja-rg \
|
||
--plan ninja-plan \
|
||
--name ninja-app \
|
||
--runtime "NODE|18-lts"
|
||
```
|
||
|
||
#### PostgreSQL
|
||
```bash
|
||
# PostgreSQL-Server erstellen
|
||
az postgres flexible-server create \
|
||
--resource-group ninja-rg \
|
||
--name ninja-db \
|
||
--admin-user ninja_user \
|
||
--admin-password secure_password \
|
||
--sku-name Standard_B1ms
|
||
```
|
||
|
||
### Google Cloud Deployment
|
||
|
||
#### Cloud Run
|
||
```yaml
|
||
# cloudbuild.yaml
|
||
steps:
|
||
- name: 'gcr.io/cloud-builders/docker'
|
||
args: ['build', '-t', 'gcr.io/$PROJECT_ID/ninja-app', '.']
|
||
- name: 'gcr.io/cloud-builders/docker'
|
||
args: ['push', 'gcr.io/$PROJECT_ID/ninja-app']
|
||
- name: 'gcr.io/cloud-builders/gcloud'
|
||
args: ['run', 'deploy', 'ninja-app', '--image', 'gcr.io/$PROJECT_ID/ninja-app', '--region', 'europe-west1']
|
||
```
|
||
|
||
## 🖥️ VPS-Deployment
|
||
|
||
### Server-Setup
|
||
```bash
|
||
#!/bin/bash
|
||
# server-setup.sh
|
||
|
||
# System aktualisieren
|
||
sudo apt update && sudo apt upgrade -y
|
||
|
||
# Node.js installieren
|
||
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
|
||
sudo apt-get install -y nodejs
|
||
|
||
# PostgreSQL installieren
|
||
sudo apt install postgresql postgresql-contrib -y
|
||
|
||
# Nginx installieren
|
||
sudo apt install nginx -y
|
||
|
||
# PM2 installieren
|
||
sudo npm install -g pm2
|
||
|
||
# Firewall konfigurieren
|
||
sudo ufw allow 22
|
||
sudo ufw allow 80
|
||
sudo ufw allow 443
|
||
sudo ufw enable
|
||
```
|
||
|
||
### Anwendung deployen
|
||
```bash
|
||
#!/bin/bash
|
||
# deploy-vps.sh
|
||
|
||
# Code aktualisieren
|
||
git pull origin main
|
||
|
||
# Abhängigkeiten installieren
|
||
npm install --production
|
||
|
||
# Datenbank migrieren
|
||
npm run migrate
|
||
|
||
# Anwendung starten
|
||
pm2 start ecosystem.config.js
|
||
|
||
# Nginx konfigurieren
|
||
sudo cp nginx.conf /etc/nginx/sites-available/ninja
|
||
sudo ln -s /etc/nginx/sites-available/ninja /etc/nginx/sites-enabled/
|
||
sudo nginx -t
|
||
sudo systemctl reload nginx
|
||
```
|
||
|
||
### PM2-Konfiguration
|
||
```javascript
|
||
// ecosystem.config.js
|
||
module.exports = {
|
||
apps: [{
|
||
name: 'ninja-app',
|
||
script: 'server.js',
|
||
instances: 'max',
|
||
exec_mode: 'cluster',
|
||
env: {
|
||
NODE_ENV: 'production',
|
||
PORT: 3000
|
||
},
|
||
error_file: './logs/err.log',
|
||
out_file: './logs/out.log',
|
||
log_file: './logs/combined.log',
|
||
time: true
|
||
}]
|
||
};
|
||
```
|
||
|
||
## 🔧 Konfiguration
|
||
|
||
### Nginx-Konfiguration
|
||
```nginx
|
||
# nginx.conf
|
||
upstream ninja_app {
|
||
server 127.0.0.1:3000;
|
||
}
|
||
|
||
server {
|
||
listen 80;
|
||
server_name ninja.reptilfpv.de;
|
||
return 301 https://$server_name$request_uri;
|
||
}
|
||
|
||
server {
|
||
listen 443 ssl http2;
|
||
server_name ninja.reptilfpv.de;
|
||
|
||
ssl_certificate /etc/nginx/ssl/cert.pem;
|
||
ssl_certificate_key /etc/nginx/ssl/key.pem;
|
||
ssl_protocols TLSv1.2 TLSv1.3;
|
||
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256;
|
||
ssl_prefer_server_ciphers off;
|
||
|
||
# Security Headers
|
||
add_header X-Frame-Options DENY;
|
||
add_header X-Content-Type-Options nosniff;
|
||
add_header X-XSS-Protection "1; mode=block";
|
||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||
|
||
# Rate Limiting
|
||
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
|
||
limit_req zone=api burst=20 nodelay;
|
||
|
||
location / {
|
||
proxy_pass http://ninja_app;
|
||
proxy_http_version 1.1;
|
||
proxy_set_header Upgrade $http_upgrade;
|
||
proxy_set_header Connection 'upgrade';
|
||
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;
|
||
proxy_cache_bypass $http_upgrade;
|
||
}
|
||
|
||
# Static Files
|
||
location /static/ {
|
||
alias /var/www/ninja/public/;
|
||
expires 1y;
|
||
add_header Cache-Control "public, immutable";
|
||
}
|
||
}
|
||
```
|
||
|
||
### SSL-Zertifikat
|
||
```bash
|
||
# Let's Encrypt
|
||
sudo apt install certbot python3-certbot-nginx -y
|
||
sudo certbot --nginx -d ninja.reptilfpv.de
|
||
|
||
# Automatische Erneuerung
|
||
echo "0 12 * * * /usr/bin/certbot renew --quiet" | sudo crontab -
|
||
```
|
||
|
||
### Datenbank-Backup
|
||
```bash
|
||
#!/bin/bash
|
||
# backup.sh
|
||
|
||
# Tägliches Backup
|
||
pg_dump -h localhost -U ninja_user -d ninjaserver | gzip > backup_$(date +%Y%m%d).sql.gz
|
||
|
||
# Alte Backups löschen (älter als 30 Tage)
|
||
find /backups -name "backup_*.sql.gz" -mtime +30 -delete
|
||
|
||
# Backup nach S3 hochladen
|
||
aws s3 cp backup_$(date +%Y%m%d).sql.gz s3://ninja-backups/
|
||
```
|
||
|
||
## 📊 Monitoring
|
||
|
||
### Application Monitoring
|
||
```javascript
|
||
// monitoring.js
|
||
const prometheus = require('prom-client');
|
||
|
||
// Metriken definieren
|
||
const httpRequestDuration = new prometheus.Histogram({
|
||
name: 'http_request_duration_seconds',
|
||
help: 'Duration of HTTP requests in seconds',
|
||
labelNames: ['method', 'route', 'status_code']
|
||
});
|
||
|
||
const activeConnections = new prometheus.Gauge({
|
||
name: 'active_connections',
|
||
help: 'Number of active connections'
|
||
});
|
||
|
||
// Metriken-Endpoint
|
||
app.get('/metrics', (req, res) => {
|
||
res.set('Content-Type', prometheus.register.contentType);
|
||
res.end(prometheus.register.metrics());
|
||
});
|
||
```
|
||
|
||
### Log-Monitoring
|
||
```bash
|
||
# Logstash-Konfiguration
|
||
input {
|
||
file {
|
||
path => "/var/log/ninja/*.log"
|
||
type => "ninja-logs"
|
||
}
|
||
}
|
||
|
||
filter {
|
||
if [type] == "ninja-logs" {
|
||
grok {
|
||
match => { "message" => "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} %{GREEDYDATA:message}" }
|
||
}
|
||
}
|
||
}
|
||
|
||
output {
|
||
elasticsearch {
|
||
hosts => ["localhost:9200"]
|
||
index => "ninja-logs-%{+YYYY.MM.dd}"
|
||
}
|
||
}
|
||
```
|
||
|
||
### Alerting
|
||
```yaml
|
||
# alertmanager.yml
|
||
global:
|
||
smtp_smarthost: 'localhost:587'
|
||
smtp_from: 'alerts@ninjaparkour.de'
|
||
|
||
route:
|
||
group_by: ['alertname']
|
||
group_wait: 10s
|
||
group_interval: 10s
|
||
repeat_interval: 1h
|
||
receiver: 'web.hook'
|
||
|
||
receivers:
|
||
- name: 'web.hook'
|
||
email_configs:
|
||
- to: 'admin@ninjaparkour.de'
|
||
subject: 'Ninja Parkour Alert: {{ .GroupLabels.alertname }}'
|
||
body: '{{ range .Alerts }}{{ .Annotations.description }}{{ end }}'
|
||
```
|
||
|
||
## 🔄 CI/CD
|
||
|
||
### GitHub Actions
|
||
```yaml
|
||
# .github/workflows/deploy.yml
|
||
name: Deploy
|
||
|
||
on:
|
||
push:
|
||
branches: [ main ]
|
||
|
||
jobs:
|
||
test:
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/checkout@v3
|
||
- uses: actions/setup-node@v3
|
||
with:
|
||
node-version: '18'
|
||
- run: npm ci
|
||
- run: npm test
|
||
|
||
deploy:
|
||
needs: test
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/checkout@v3
|
||
- name: Deploy to production
|
||
run: |
|
||
ssh user@server 'cd /var/www/ninja && git pull && npm install && pm2 restart ninja-app'
|
||
```
|
||
|
||
### GitLab CI
|
||
```yaml
|
||
# .gitlab-ci.yml
|
||
stages:
|
||
- test
|
||
- deploy
|
||
|
||
test:
|
||
stage: test
|
||
script:
|
||
- npm ci
|
||
- npm test
|
||
|
||
deploy:
|
||
stage: deploy
|
||
script:
|
||
- ssh user@server 'cd /var/www/ninja && git pull && npm install && pm2 restart ninja-app'
|
||
only:
|
||
- main
|
||
```
|
||
|
||
### Jenkins Pipeline
|
||
```groovy
|
||
// Jenkinsfile
|
||
pipeline {
|
||
agent any
|
||
|
||
stages {
|
||
stage('Test') {
|
||
steps {
|
||
sh 'npm ci'
|
||
sh 'npm test'
|
||
}
|
||
}
|
||
|
||
stage('Deploy') {
|
||
steps {
|
||
sh 'ssh user@server "cd /var/www/ninja && git pull && npm install && pm2 restart ninja-app"'
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
## 🔧 Wartung
|
||
|
||
### Automatische Updates
|
||
```bash
|
||
#!/bin/bash
|
||
# auto-update.sh
|
||
|
||
# System-Updates
|
||
sudo apt update && sudo apt upgrade -y
|
||
|
||
# Anwendung-Updates
|
||
cd /var/www/ninja
|
||
git pull origin main
|
||
npm install --production
|
||
pm2 restart ninja-app
|
||
|
||
# Datenbank-Updates
|
||
npm run migrate
|
||
```
|
||
|
||
### Health Checks
|
||
```bash
|
||
#!/bin/bash
|
||
# health-check.sh
|
||
|
||
# Anwendung prüfen
|
||
curl -f http://localhost:3000/health || exit 1
|
||
|
||
# Datenbank prüfen
|
||
psql -d ninjaserver -c "SELECT NOW();" || exit 1
|
||
|
||
# Speicher prüfen
|
||
if [ $(df / | awk 'NR==2{print $5}' | sed 's/%//') -gt 80 ]; then
|
||
echo "Disk space low"
|
||
exit 1
|
||
fi
|
||
```
|
||
|
||
### Rollback-Strategie
|
||
```bash
|
||
#!/bin/bash
|
||
# rollback.sh
|
||
|
||
# Vorherige Version wiederherstellen
|
||
cd /var/www/ninja
|
||
git checkout HEAD~1
|
||
npm install --production
|
||
pm2 restart ninja-app
|
||
|
||
# Datenbank-Rollback
|
||
psql -d ninjaserver < backup_previous.sql
|
||
```
|
||
|
||
---
|
||
|
||
**Hinweis:** Diese Deployment-Anleitung sollte an Ihre spezifischen Anforderungen angepasst werden. Testen Sie alle Schritte in einer Staging-Umgebung vor der Produktionsbereitstellung.
|