diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..32ec24f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,61 @@ +# Node modules +node_modules/ +npm-debug.log +yarn-error.log + +# Environment files +.env +.env.local +.env.*.local + +# Git +.git/ +.gitignore + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db + +# Logs +logs/ +*.log + +# Database (will be in volume) +database/ +*.db +*.db-journal + +# Build artifacts +dist/ +build/ +.cache/ + +# Documentation +*.md +docs/ + +# Docker +Dockerfile* +docker-compose*.yml +.dockerignore + +# Deployment +deploy.sh +systemd/ +nginx/ + +# Testing +coverage/ +.nyc_output/ + +# Temporary files +tmp/ +temp/ + diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index 56c50b7..da9c28e 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -338,7 +338,7 @@ After=network.target [Service] Type=simple -User=www-data +User=oltalama WorkingDirectory=/opt/oltalama/backend Environment=NODE_ENV=production ExecStart=/usr/bin/node /opt/oltalama/backend/src/app.js @@ -362,7 +362,7 @@ After=network.target [Service] Type=simple -User=www-data +User=oltalama WorkingDirectory=/opt/oltalama/frontend Environment=NODE_ENV=production ExecStart=/usr/bin/npm run preview @@ -522,7 +522,7 @@ const rl = readline.createInterface({ ```bash # Proje dizini izinleri -sudo chown -R www-data:www-data /opt/oltalama +sudo chown -R oltalama:oltalama /opt/oltalama sudo chmod -R 755 /opt/oltalama # .env dosyalarını koru @@ -687,7 +687,7 @@ pm2 logs --lines 100 delaycompress missingok notifempty - create 0640 www-data www-data + create 0640 oltalama oltalama sharedscripts postrotate pm2 reloadLogs diff --git a/DOCKER.md b/DOCKER.md new file mode 100644 index 0000000..530dea3 --- /dev/null +++ b/DOCKER.md @@ -0,0 +1,500 @@ +# 🐳 Docker Deployment Guide + +## Oltalama Test Yönetim Paneli - Docker ile Kurulum + +Bu dokümantasyon, projeyi Docker ve Docker Compose kullanarak nasıl çalıştıracağınızı açıklar. + +--- + +## 📋 İçindekiler + +- [Gereksinimler](#gereksinimler) +- [Hızlı Başlangıç](#hızlı-başlangıç) +- [Development Modu](#development-modu) +- [Production Modu](#production-modu) +- [Ortam Değişkenleri](#ortam-değişkenleri) +- [Veri Yedekleme](#veri-yedekleme) +- [İleri Seviye Kullanım](#ileri-seviye-kullanım) + +--- + +## 🔧 Gereksinimler + +- **Docker**: 20.10 veya üzeri +- **Docker Compose**: 2.0 veya üzeri +- **Git**: (projeyi klonlamak için) + +### Docker Kurulumu + +#### Ubuntu/Debian: +```bash +# Docker kurulumu +curl -fsSL https://get.docker.com -o get-docker.sh +sudo sh get-docker.sh + +# Docker Compose kurulumu (eğer yoksa) +sudo apt-get install docker-compose-plugin + +# Kullanıcıyı docker grubuna ekle +sudo usermod -aG docker $USER +newgrp docker +``` + +#### RedHat/Oracle/CentOS: +```bash +# Docker kurulumu +sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin + +# Docker'ı başlat ve aktifleştir +sudo systemctl start docker +sudo systemctl enable docker + +# Kullanıcıyı docker grubuna ekle +sudo usermod -aG docker $USER +newgrp docker +``` + +--- + +## 🚀 Hızlı Başlangıç + +### 1. Projeyi Klonlayın + +```bash +git clone oltalama +cd oltalama +``` + +### 2. Environment Dosyasını Hazırlayın + +```bash +# .env.docker dosyasını kopyalayın +cp .env.docker .env + +# Editör ile açın ve konfigüre edin +nano .env +``` + +**Minimum gerekli ayarlar:** +```env +SESSION_SECRET=very-strong-random-secret-here +GMAIL_USER=your-email@gmail.com +GMAIL_APP_PASSWORD=your-gmail-app-password +TELEGRAM_BOT_TOKEN=your-bot-token +TELEGRAM_CHAT_ID=your-chat-id +``` + +### 3. Production Modunda Başlatın + +```bash +# Container'ları build edin ve başlatın +docker compose up -d + +# Logları görüntüleyin +docker compose logs -f +``` + +### 4. Admin Kullanıcısı Oluşturun + +İlk çalıştırmada admin kullanıcısı oluşturmanız gerekir: + +```bash +# Backend container'a bağlanın +docker compose exec backend sh + +# Admin kullanıcı scripti çalıştırın +node scripts/create-admin.js + +# Container'dan çıkın +exit +``` + +### 5. Uygulamaya Erişin + +- **Frontend**: http://localhost:4173 +- **Backend API**: http://localhost:3000 +- **Health Check**: http://localhost:3000/health + +--- + +## 💻 Development Modu + +Development modunda hot-reload aktif olur ve kod değişiklikleri anında yansır. + +### Başlatma + +```bash +# Development compose ile başlat +docker compose -f docker-compose.dev.yml up + +# Veya arka planda çalıştır +docker compose -f docker-compose.dev.yml up -d +``` + +### Özellikler + +- ✅ **Hot Reload**: Kod değişiklikleri anında yansır +- ✅ **Volume Mount**: Local klasörler container'a mount edilir +- ✅ **Debug Modu**: Detaylı log çıktıları +- ✅ **Nodemon**: Backend için otomatik restart + +### Development Portları + +- **Frontend (Vite Dev Server)**: http://localhost:5173 +- **Backend**: http://localhost:3000 + +--- + +## 🏭 Production Modu + +Production modu için optimize edilmiş, multi-stage build ile küçük image boyutu. + +### Başlatma + +```bash +# Production compose ile başlat +docker compose up -d + +# Durum kontrolü +docker compose ps + +# Logları görüntüle +docker compose logs -f backend +docker compose logs -f frontend +``` + +### Container Yönetimi + +```bash +# Tüm servisleri durdur +docker compose stop + +# Tüm servisleri başlat +docker compose start + +# Tüm servisleri yeniden başlat +docker compose restart + +# Servisleri kaldır (veri korunur) +docker compose down + +# Servisleri ve volume'leri kaldır (VERİ SİLİNİR!) +docker compose down -v +``` + +### Build İşlemleri + +```bash +# Image'ları yeniden build et +docker compose build + +# Cache kullanmadan build et +docker compose build --no-cache + +# Belirli bir servisi build et +docker compose build backend +``` + +--- + +## 🔐 Ortam Değişkenleri + +### Backend Değişkenleri + +| Değişken | Açıklama | Varsayılan | Zorunlu | +|----------|----------|------------|---------| +| `NODE_ENV` | Çalışma ortamı | `production` | ❌ | +| `PORT` | Backend portu | `3000` | ❌ | +| `SESSION_SECRET` | Session şifreleme anahtarı | - | ✅ | +| `GMAIL_USER` | Gmail hesabı | - | ✅ | +| `GMAIL_APP_PASSWORD` | Gmail uygulama şifresi | - | ✅ | +| `TELEGRAM_BOT_TOKEN` | Telegram bot token | - | ✅ | +| `TELEGRAM_CHAT_ID` | Telegram chat ID | - | ✅ | +| `DOMAIN_URL` | Backend domain | `http://localhost:3000` | ❌ | +| `FRONTEND_URL` | Frontend domain | `http://localhost:4173` | ❌ | +| `OLLAMA_SERVER_URL` | Ollama AI server URL | `http://host.docker.internal:11434` | ❌ | +| `OLLAMA_MODEL` | Ollama model adı | `llama3.2:latest` | ❌ | + +### Frontend Değişkenleri + +| Değişken | Açıklama | Varsayılan | Zorunlu | +|----------|----------|------------|---------| +| `VITE_API_URL` | Backend API URL | `http://localhost:3000` | ✅ | + +--- + +## 💾 Veri Yedekleme + +### Manuel Yedekleme + +```bash +# Database yedekle +docker compose exec backend sh -c "cd database && tar czf /tmp/backup.tar.gz *.db" +docker compose cp backend:/tmp/backup.tar.gz ./backup-$(date +%Y%m%d).tar.gz + +# Logs yedekle +docker compose exec backend sh -c "cd logs && tar czf /tmp/logs-backup.tar.gz *.log" +docker compose cp backend:/tmp/logs-backup.tar.gz ./logs-backup-$(date +%Y%m%d).tar.gz +``` + +### Otomatik Yedekleme (Cron) + +```bash +# Yedekleme scripti oluştur +cat > backup.sh << 'EOF' +#!/bin/bash +BACKUP_DIR="/backup/oltalama" +DATE=$(date +%Y%m%d_%H%M%S) + +mkdir -p $BACKUP_DIR + +# Database backup +docker compose exec -T backend sh -c "cd database && tar czf - *.db" > "$BACKUP_DIR/db-$DATE.tar.gz" + +# Eski yedekleri sil (30 günden eski) +find $BACKUP_DIR -name "db-*.tar.gz" -mtime +30 -delete + +echo "Backup completed: $DATE" +EOF + +chmod +x backup.sh + +# Crontab'a ekle (her gün 02:00'de) +(crontab -l 2>/dev/null; echo "0 2 * * * /path/to/backup.sh >> /var/log/oltalama-backup.log 2>&1") | crontab - +``` + +### Geri Yükleme + +```bash +# Database geri yükle +docker compose cp ./backup-20250101.tar.gz backend:/tmp/ +docker compose exec backend sh -c "cd database && tar xzf /tmp/backup-20250101.tar.gz" +docker compose restart backend +``` + +--- + +## 🔧 İleri Seviye Kullanım + +### Nginx ile Reverse Proxy + +Nginx reverse proxy eklemek için: + +```bash +# Nginx profili ile başlat +docker compose --profile with-nginx up -d +``` + +`nginx.conf` dosyasını düzenleyin: + +```nginx +# nginx/nginx.conf +server { + listen 80; + server_name yourdomain.com; + + location / { + proxy_pass http://frontend:4173; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } + + location /api/ { + proxy_pass http://backend:3000/api/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } +} +``` + +### Resource Limits + +Production ortamında resource limitleri ekleyin: + +```yaml +# docker-compose.yml içine ekle +services: + backend: + # ... diğer ayarlar + deploy: + resources: + limits: + cpus: '1' + memory: 512M + reservations: + cpus: '0.5' + memory: 256M +``` + +### Health Check Monitoring + +Container'ların sağlık durumunu izleyin: + +```bash +# Health status kontrolü +docker compose ps + +# Detaylı health check logları +docker inspect --format='{{json .State.Health}}' oltalama-backend | jq +``` + +### Ollama ile Kullanım + +Eğer Ollama host makinede çalışıyorsa: + +```bash +# Host'tan Ollama'ya erişim için +# .env dosyasında: +OLLAMA_SERVER_URL=http://host.docker.internal:11434 +OLLAMA_MODEL=llama3.2:latest +``` + +Ollama'yı da Docker'da çalıştırmak için: + +```yaml +# docker-compose.yml'e ekle +services: + ollama: + image: ollama/ollama:latest + container_name: oltalama-ollama + restart: unless-stopped + ports: + - "11434:11434" + volumes: + - ollama-data:/root/.ollama + networks: + - oltalama-network + +volumes: + ollama-data: + driver: local +``` + +Sonra `.env` dosyasında: +```env +OLLAMA_SERVER_URL=http://ollama:11434 +``` + +--- + +## 🐛 Troubleshooting + +### Problem: Container başlamıyor + +```bash +# Logları kontrol et +docker compose logs backend +docker compose logs frontend + +# Container'ı interaktif başlat +docker compose run --rm backend sh +``` + +### Problem: Database erişim hatası + +```bash +# Volume'leri kontrol et +docker volume ls +docker volume inspect oltalama_backend-data + +# İzinleri düzelt +docker compose exec backend chown -R oltalama:oltalama /app/database +``` + +### Problem: Port conflict + +```bash +# Kullanılan portları kontrol et +sudo lsof -i :3000 +sudo lsof -i :4173 + +# Farklı port kullan +docker compose up -d --force-recreate +``` + +### Problem: Image boyutu çok büyük + +```bash +# Kullanılmayan image'ları temizle +docker system prune -a + +# Build cache'i temizle +docker builder prune +``` + +--- + +## 📊 Monitoring + +### Container İstatistikleri + +```bash +# Gerçek zamanlı resource kullanımı +docker stats + +# Belirli container'lar için +docker stats oltalama-backend oltalama-frontend +``` + +### Log Yönetimi + +```bash +# Son 100 satır +docker compose logs --tail=100 backend + +# Gerçek zamanlı takip +docker compose logs -f + +# Belirli bir zaman aralığı +docker compose logs --since="2025-01-01T00:00:00" + +# Belirli bir service +docker compose logs backend +``` + +--- + +## 🚀 Production Deployment Checklist + +- [ ] `.env` dosyasını production değerleri ile doldur +- [ ] `SESSION_SECRET` için güçlü random string oluştur +- [ ] Gmail App Password oluştur ve ayarla +- [ ] Telegram bot token ve chat ID ayarla +- [ ] Domain URL'lerini güncelle +- [ ] Nginx reverse proxy yapılandır (opsiyonel) +- [ ] SSL/TLS sertifikası ekle +- [ ] Firewall kurallarını ayarla +- [ ] Admin kullanıcı oluştur +- [ ] Otomatik yedekleme sistemi kur +- [ ] Health check monitoring kur +- [ ] Log rotation yapılandır + +--- + +## 📚 Ek Kaynaklar + +- [Docker Documentation](https://docs.docker.com/) +- [Docker Compose Documentation](https://docs.docker.com/compose/) +- [Best Practices for Node.js in Docker](https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md) + +--- + +## 🆘 Destek + +Sorun yaşıyorsanız: + +1. Logları kontrol edin: `docker compose logs` +2. Container durumunu kontrol edin: `docker compose ps` +3. Health check durumunu kontrol edin +4. Issue açın veya dokümantasyonu inceleyin + +--- + +**🎉 Artık Docker ile hazırsınız!** + diff --git a/SECURITY.md b/SECURITY.md index 62a71c5..bb60f90 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -155,11 +155,11 @@ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; prelo ```bash # Database dosya izinleri sudo chmod 600 /opt/oltalama/backend/database/oltalama.db -sudo chown www-data:www-data /opt/oltalama/backend/database/oltalama.db +sudo chown oltalama:oltalama /opt/oltalama/backend/database/oltalama.db # Backup dizini izinleri sudo chmod 700 /opt/oltalama/backups -sudo chown www-data:www-data /opt/oltalama/backups +sudo chown oltalama:oltalama /opt/oltalama/backups ``` #### Düzenli Yedekleme @@ -201,8 +201,8 @@ sudo chmod 600 /opt/oltalama/backend/.env sudo chmod 600 /opt/oltalama/frontend/.env # Sahibi ayarla -sudo chown www-data:www-data /opt/oltalama/backend/.env -sudo chown www-data:www-data /opt/oltalama/frontend/.env +sudo chown oltalama:oltalama /opt/oltalama/backend/.env +sudo chown oltalama:oltalama /opt/oltalama/frontend/.env ``` #### Session Secret @@ -273,7 +273,7 @@ echo ".env" >> .gitignore ```bash # Log dizini izinleri sudo chmod 750 /var/log/oltalama -sudo chown www-data:www-data /var/log/oltalama +sudo chown oltalama:oltalama /var/log/oltalama # Log dosyaları izinleri sudo chmod 640 /var/log/oltalama/*.log @@ -290,7 +290,7 @@ sudo chmod 640 /var/log/oltalama/*.log delaycompress missingok notifempty - create 0640 www-data www-data + create 0640 oltalama oltalama sharedscripts postrotate pm2 reloadLogs diff --git a/backend/.dockerignore b/backend/.dockerignore new file mode 100644 index 0000000..0f4bb98 --- /dev/null +++ b/backend/.dockerignore @@ -0,0 +1,43 @@ +# Node modules +node_modules/ +npm-debug.log + +# Environment files +.env +.env.local + +# Git +.git/ +.gitignore + +# Database (will be in volume) +database/ +*.db +*.db-journal + +# Logs (will be in volume) +logs/ +*.log + +# Documentation +*.md + +# IDE +.vscode/ +.idea/ + +# OS +.DS_Store + +# Testing +coverage/ +.nyc_output/ + +# Migrations (already applied) +migrations/ +seeders/ + +# Temporary +tmp/ +temp/ + diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..06d2935 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,54 @@ +# Backend Dockerfile +# Multi-stage build for optimized production image + +# Stage 1: Build stage +FROM node:20-alpine AS builder + +WORKDIR /app + +# Copy package files +COPY package*.json ./ + +# Install dependencies +RUN npm ci --only=production + +# Stage 2: Production stage +FROM node:20-alpine + +# Install required packages +RUN apk add --no-cache \ + sqlite \ + tini + +# Create app user +RUN addgroup -g 1001 -S oltalama && \ + adduser -S oltalama -u 1001 -G oltalama + +WORKDIR /app + +# Copy dependencies from builder +COPY --from=builder /app/node_modules ./node_modules + +# Copy application code +COPY --chown=oltalama:oltalama . . + +# Create necessary directories +RUN mkdir -p database logs && \ + chown -R oltalama:oltalama /app + +# Switch to non-root user +USER oltalama + +# Expose port +EXPOSE 3000 + +# Health check +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD node -e "require('http').get('http://localhost:3000/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})" + +# Use tini as entrypoint for proper signal handling +ENTRYPOINT ["/sbin/tini", "--"] + +# Start application +CMD ["node", "src/app.js"] + diff --git a/backend/Dockerfile.dev b/backend/Dockerfile.dev new file mode 100644 index 0000000..fed6da5 --- /dev/null +++ b/backend/Dockerfile.dev @@ -0,0 +1,33 @@ +# Backend Development Dockerfile +# Hot reload enabled with nodemon + +FROM node:20-alpine + +# Install required packages +RUN apk add --no-cache \ + sqlite \ + tini + +WORKDIR /app + +# Copy package files +COPY package*.json ./ + +# Install all dependencies (including dev) +RUN npm install + +# Copy application code +COPY . . + +# Create necessary directories +RUN mkdir -p database logs + +# Expose port +EXPOSE 3000 + +# Use tini as entrypoint +ENTRYPOINT ["/sbin/tini", "--"] + +# Start with nodemon for hot reload +CMD ["npm", "run", "dev"] + diff --git a/deploy.sh b/deploy.sh index 8cdc406..a03213a 100755 --- a/deploy.sh +++ b/deploy.sh @@ -19,7 +19,7 @@ NC='\033[0m' # No Color INSTALL_DIR="/opt/oltalama" LOG_DIR="/var/log/oltalama" BACKUP_DIR="${INSTALL_DIR}/backups" -USER="www-data" +USER="oltalama" # Tüm sistemler için ortak kullanıcı NODE_VERSION="20" # Fonksiyonlar @@ -62,6 +62,21 @@ check_os() { OS=$ID VERSION=$VERSION_ID print_success "İşletim sistemi tespit edildi: $PRETTY_NAME" + + # Paket yöneticisi tespit et + if command -v apt-get &> /dev/null; then + PKG_MANAGER="apt" + print_info "Paket yöneticisi: APT (Debian/Ubuntu)" + elif command -v dnf &> /dev/null; then + PKG_MANAGER="dnf" + print_info "Paket yöneticisi: DNF (RedHat/Oracle/Fedora)" + elif command -v yum &> /dev/null; then + PKG_MANAGER="yum" + print_info "Paket yöneticisi: YUM (RedHat/CentOS)" + else + print_error "Desteklenen paket yöneticisi bulunamadı!" + exit 1 + fi else print_error "İşletim sistemi tespit edilemedi!" exit 1 @@ -80,8 +95,13 @@ install_nodejs() { fi # NodeSource repository ekle - curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - - apt-get install -y nodejs + if [[ "$PKG_MANAGER" == "apt" ]]; then + curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - + apt-get install -y nodejs + elif [[ "$PKG_MANAGER" == "dnf" ]] || [[ "$PKG_MANAGER" == "yum" ]]; then + curl -fsSL https://rpm.nodesource.com/setup_${NODE_VERSION}.x | bash - + $PKG_MANAGER install -y nodejs + fi print_success "Node.js $(node -v) kuruldu." print_success "npm $(npm -v) kuruldu." @@ -89,8 +109,20 @@ install_nodejs() { install_dependencies() { print_info "Sistem bağımlılıkları kuruluyor..." - apt-get update - apt-get install -y git curl wget build-essential sqlite3 + + if [[ "$PKG_MANAGER" == "apt" ]]; then + apt-get update + apt-get install -y git curl wget build-essential sqlite3 + elif [[ "$PKG_MANAGER" == "dnf" ]] || [[ "$PKG_MANAGER" == "yum" ]]; then + $PKG_MANAGER update -y + # EPEL repository (bazı paketler için gerekli) + $PKG_MANAGER install -y epel-release 2>/dev/null || true + # Paketleri kur + $PKG_MANAGER install -y git curl wget gcc-c++ make sqlite + # Development tools + $PKG_MANAGER groupinstall -y "Development Tools" 2>/dev/null || true + fi + print_success "Sistem bağımlılıkları kuruldu." } @@ -110,6 +142,18 @@ setup_directories() { print_success "Dizinler oluşturuldu." } +create_user() { + print_info "Sistem kullanıcısı kontrol ediliyor..." + + if id "$USER" &>/dev/null; then + print_success "Kullanıcı '$USER' zaten mevcut." + else + print_info "Kullanıcı '$USER' oluşturuluyor..." + useradd -r -s /bin/bash -d $INSTALL_DIR -m $USER + print_success "Kullanıcı '$USER' oluşturuldu." + fi +} + install_project() { print_info "Proje dosyaları kontrol ediliyor..." @@ -441,6 +485,9 @@ setup_firewall() { print_info "Firewall ayarlanıyor..." if command -v ufw &> /dev/null; then + # Ubuntu/Debian - UFW + print_info "UFW kullanılıyor..." + # SSH izin ver ufw allow 22/tcp comment 'SSH' @@ -460,9 +507,30 @@ setup_firewall() { echo "y" | ufw enable fi - print_success "Firewall ayarlandı." + print_success "Firewall ayarlandı (UFW)." + elif command -v firewall-cmd &> /dev/null; then + # RedHat/Oracle/CentOS - firewalld + print_info "firewalld kullanılıyor..." + + # firewalld'yi başlat ve aktifleştir + systemctl start firewalld 2>/dev/null || true + systemctl enable firewalld 2>/dev/null || true + + # HTTP/HTTPS izin ver + firewall-cmd --permanent --add-service=http + firewall-cmd --permanent --add-service=https + firewall-cmd --permanent --add-service=ssh + + # Backend ve Frontend portları sadece localhost'tan erişilebilir + # (reverse proxy kullanılacağı için dışarıdan erişim kapalı) + + # Yeniden yükle + firewall-cmd --reload + + print_success "Firewall ayarlandı (firewalld)." else - print_warning "UFW bulunamadı, firewall ayarları atlanıyor." + print_warning "Firewall bulunamadı, firewall ayarları atlanıyor." + print_warning "Güvenlik için manuel olarak firewall yapılandırmanız önerilir." fi } @@ -540,6 +608,7 @@ main() { install_dependencies install_nodejs install_pm2 + create_user setup_directories install_project install_backend diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 0000000..0c82de0 --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,67 @@ +version: '3.8' + +# Development Docker Compose +# Hot reload enabled, volumes mounted + +services: + # Backend Service (Development) + backend: + build: + context: ./backend + dockerfile: Dockerfile.dev + container_name: oltalama-backend-dev + restart: unless-stopped + ports: + - "3000:3000" + environment: + - NODE_ENV=development + - PORT=3000 + - SESSION_SECRET=dev-secret-change-in-production + - GMAIL_USER=${GMAIL_USER} + - GMAIL_APP_PASSWORD=${GMAIL_APP_PASSWORD} + - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN} + - TELEGRAM_CHAT_ID=${TELEGRAM_CHAT_ID} + - DOMAIN_URL=http://localhost:3000 + - FRONTEND_URL=http://localhost:5173 + - OLLAMA_SERVER_URL=${OLLAMA_SERVER_URL:-http://host.docker.internal:11434} + - OLLAMA_MODEL=${OLLAMA_MODEL:-llama3.2:latest} + volumes: + - ./backend:/app + - /app/node_modules + - backend-data:/app/database + - backend-logs:/app/logs + networks: + - oltalama-network + command: npm run dev + + # Frontend Service (Development) + frontend: + build: + context: ./frontend + dockerfile: Dockerfile.dev + container_name: oltalama-frontend-dev + restart: unless-stopped + ports: + - "5173:5173" + environment: + - NODE_ENV=development + - VITE_API_URL=http://localhost:3000 + volumes: + - ./frontend:/app + - /app/node_modules + depends_on: + - backend + networks: + - oltalama-network + command: npm run dev + +volumes: + backend-data: + driver: local + backend-logs: + driver: local + +networks: + oltalama-network: + driver: bridge + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..7282776 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,89 @@ +version: '3.8' + +services: + # Backend Service + backend: + build: + context: ./backend + dockerfile: Dockerfile + container_name: oltalama-backend + restart: unless-stopped + ports: + - "3000:3000" + environment: + - NODE_ENV=production + - PORT=3000 + - SESSION_SECRET=${SESSION_SECRET:-change-this-secret-in-production} + - GMAIL_USER=${GMAIL_USER} + - GMAIL_APP_PASSWORD=${GMAIL_APP_PASSWORD} + - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN} + - TELEGRAM_CHAT_ID=${TELEGRAM_CHAT_ID} + - DOMAIN_URL=${DOMAIN_URL:-http://localhost:3000} + - FRONTEND_URL=${FRONTEND_URL:-http://localhost:4173} + - OLLAMA_SERVER_URL=${OLLAMA_SERVER_URL:-http://host.docker.internal:11434} + - OLLAMA_MODEL=${OLLAMA_MODEL:-llama3.2:latest} + volumes: + - backend-data:/app/database + - backend-logs:/app/logs + networks: + - oltalama-network + healthcheck: + test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + # Frontend Service + frontend: + build: + context: ./frontend + dockerfile: Dockerfile + container_name: oltalama-frontend + restart: unless-stopped + ports: + - "4173:4173" + environment: + - NODE_ENV=production + - VITE_API_URL=${VITE_API_URL:-http://localhost:3000} + depends_on: + backend: + condition: service_healthy + networks: + - oltalama-network + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:4173"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + # Nginx Reverse Proxy (Optional) + nginx: + image: nginx:alpine + container_name: oltalama-nginx + restart: unless-stopped + ports: + - "80:80" + - "443:443" + volumes: + - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro + - ./nginx/ssl:/etc/nginx/ssl:ro + depends_on: + - backend + - frontend + networks: + - oltalama-network + profiles: + - with-nginx + +volumes: + backend-data: + driver: local + backend-logs: + driver: local + +networks: + oltalama-network: + driver: bridge + diff --git a/frontend/.dockerignore b/frontend/.dockerignore new file mode 100644 index 0000000..e6472fe --- /dev/null +++ b/frontend/.dockerignore @@ -0,0 +1,33 @@ +# Node modules +node_modules/ +npm-debug.log + +# Environment files +.env +.env.local + +# Git +.git/ +.gitignore + +# Build artifacts +dist/ +.cache/ + +# Documentation +*.md + +# IDE +.vscode/ +.idea/ + +# OS +.DS_Store + +# Testing +coverage/ + +# Temporary +tmp/ +temp/ + diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..c5092c9 --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,49 @@ +# Frontend Dockerfile +# Multi-stage build for optimized production image + +# Stage 1: Build stage +FROM node:20-alpine AS builder + +WORKDIR /app + +# Copy package files +COPY package*.json ./ + +# Install dependencies +RUN npm ci + +# Copy application code +COPY . . + +# Build for production +RUN npm run build + +# Stage 2: Production stage +FROM node:20-alpine + +# Create app user +RUN addgroup -g 1001 -S oltalama && \ + adduser -S oltalama -u 1001 -G oltalama + +WORKDIR /app + +# Copy built assets from builder +COPY --from=builder --chown=oltalama:oltalama /app/dist ./dist +COPY --from=builder --chown=oltalama:oltalama /app/package*.json ./ + +# Install only production dependencies (for preview server) +RUN npm ci --only=production + +# Switch to non-root user +USER oltalama + +# Expose port +EXPOSE 4173 + +# Health check +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost:4173 || exit 1 + +# Start preview server +CMD ["npm", "run", "preview", "--", "--host", "0.0.0.0"] + diff --git a/frontend/Dockerfile.dev b/frontend/Dockerfile.dev new file mode 100644 index 0000000..c8b4d7b --- /dev/null +++ b/frontend/Dockerfile.dev @@ -0,0 +1,22 @@ +# Frontend Development Dockerfile +# Hot reload enabled with Vite + +FROM node:20-alpine + +WORKDIR /app + +# Copy package files +COPY package*.json ./ + +# Install all dependencies (including dev) +RUN npm install + +# Copy application code +COPY . . + +# Expose Vite dev server port +EXPOSE 5173 + +# Start Vite dev server with host binding +CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"] + diff --git a/systemd/oltalama-backend.service b/systemd/oltalama-backend.service index 0142c97..1aef9fb 100644 --- a/systemd/oltalama-backend.service +++ b/systemd/oltalama-backend.service @@ -5,8 +5,8 @@ After=network.target [Service] Type=simple -User=www-data -Group=www-data +User=oltalama +Group=oltalama WorkingDirectory=/opt/oltalama/backend Environment=NODE_ENV=production Environment=PORT=3000 diff --git a/systemd/oltalama-frontend.service b/systemd/oltalama-frontend.service index 013cdb1..c429013 100644 --- a/systemd/oltalama-frontend.service +++ b/systemd/oltalama-frontend.service @@ -5,8 +5,8 @@ After=network.target oltalama-backend.service [Service] Type=simple -User=www-data -Group=www-data +User=oltalama +Group=oltalama WorkingDirectory=/opt/oltalama/frontend Environment=NODE_ENV=production Environment=PORT=4173