diff --git a/DOCKER.md b/DOCKER.md new file mode 100644 index 0000000..ab215ca --- /dev/null +++ b/DOCKER.md @@ -0,0 +1,183 @@ +# 🐳 Docker Deployment Guide + +> **Hướng dẫn triển khai Tech Gadget Manager trên Docker / Unraid / NAS** + +--- + +## ⚠️ CẢNH BÁO QUAN TRỌNG + +### Data Loss với `--accept-data-loss` + +File `docker-entrypoint.sh` sử dụng: +```bash +npx prisma db push --accept-data-loss --skip-generate +``` + +**Điều này có nghĩa:** +- Mỗi khi schema Prisma thay đổi (thêm/xóa field, đổi type), Prisma **CÓ THỂ XÓA DỮ LIỆU** +- User, Items, Locations **SẼ BỊ MẤT** nếu schema không tương thích + +### 🛡️ BACKUP TRƯỚC KHI UPDATE + +```bash +# Trên Unraid/NAS, backup file database trước khi update: +cp ./db/prod.db ./db/prod.db.backup.$(date +%Y%m%d) +``` + +--- + +## 📦 Cấu Trúc Files + +``` +├── Dockerfile # Multi-stage build +├── docker-compose.yml # Compose config cho Unraid +├── docker-entrypoint.sh # Startup script (migration + start) +└── src/lib/db.ts # Database connection logic +``` + +--- + +## 🔧 Cách Hoạt Động + +### 1. Database Connection (`src/lib/db.ts`) + +```typescript +// PRIORITY 1: Use DATABASE_URL from environment (Docker) +if (process.env.DATABASE_URL) { + return new PrismaClient(); // Uses env var directly +} + +// PRIORITY 2: Vercel /tmp strategy (Read-only filesystem) +// Copy dev.db to /tmp + +// PRIORITY 3: Development mode +``` + +**Quan trọng:** Khi `DATABASE_URL` được set (trong docker-compose.yml), Prisma sẽ dùng path đó trực tiếp. + +### 2. Docker Compose (`docker-compose.yml`) + +```yaml +services: + app: + image: ghcr.io/duongcamcute/tech-gadget-manager:latest + environment: + - DATABASE_URL=file:/app/db/prod.db # ← Path TRONG container + - NODE_ENV=production + - DISABLE_SECURE_COOKIES=true # ← Cho HTTP (không có SSL) + - JWT_SECRET=your_secret_here # ← ĐỔI THÀNH RANDOM STRING + volumes: + - ./db:/app/db # ← Data persist qua restart/update + - ./uploads:/app/public/uploads +``` + +### 3. Entrypoint (`docker-entrypoint.sh`) + +1. Fix permissions cho `/app/db` volume +2. Chạy `prisma db push` để sync schema +3. Start `node server.js` + +--- + +## 🚀 Triển Khai + +### Option 1: Docker Run (Đơn giản) + +```bash +docker run -d \ + --name tech-gadget-manager \ + --restart unless-stopped \ + -p 3000:3000 \ + -v $(pwd)/db:/app/db \ + -e DATABASE_URL="file:/app/db/prod.db" \ + -e JWT_SECRET="change_this_to_random_string" \ + -e DISABLE_SECURE_COOKIES=true \ + ghcr.io/duongcamcute/tech-gadget-manager:latest +``` + +### Option 2: Docker Compose (Khuyến nghị) + +```bash +# Clone hoặc tạo docker-compose.yml +wget https://raw.githubusercontent.com/duongcamcute/tech-gadget-manager/main/docker-compose.yml + +# Khởi chạy +docker-compose up -d + +# Xem logs +docker-compose logs -f +``` + +### Option 3: Unraid Community Applications + +1. Tìm "Tech Gadget Manager" trong Community Apps +2. Cấu hình paths và variables +3. Apply + +--- + +## 🔄 Update Container + +```bash +# 1. BACKUP DATABASE TRƯỚC +cp ./db/prod.db ./db/prod.db.backup + +# 2. Pull image mới +docker-compose pull + +# 3. Restart container +docker-compose down && docker-compose up -d +``` + +--- + +## 🐛 Troubleshooting + +### Container crash loop +```bash +docker logs tech-gadget-manager +``` +Thường do: +- Permission denied trên `/app/db` → Kiểm tra ownership +- Schema conflict → Xóa file `prod.db` và tạo lại (mất data!) + +### Database file bị lock +```bash +# Trong container +rm /app/db/prod.db-journal /app/db/prod.db-wal /app/db/prod.db-shm +``` + +### Permission denied +```bash +# Trên host +sudo chown -R 1001:1001 ./db +``` + +--- + +## 📁 Environment Variables + +| Variable | Required | Default | Description | +|----------|----------|---------|-------------| +| `DATABASE_URL` | ✅ Yes | - | Path to SQLite file (`file:/app/db/prod.db`) | +| `NODE_ENV` | No | production | Environment mode | +| `JWT_SECRET` | ⚠️ Recommended | hardcoded | Secret for JWT tokens | +| `DISABLE_SECURE_COOKIES` | For HTTP | false | Set `true` if not using HTTPS | +| `NEXT_PUBLIC_DEMO_MODE` | No | false | Enable read-only demo mode | + +--- + +## 👨‍💻 Dành Cho Agent/Developer + +Khi thay đổi schema Prisma (`prisma/schema.prisma`): + +1. **Thêm field mới (nullable):** An toàn, không mất data +2. **Thêm field mới (required):** Cần `@default()` hoặc sẽ fail +3. **Xóa field/table:** `--accept-data-loss` sẽ xóa data! +4. **Đổi type field:** Có thể mất data + +**Best practice:** Luôn test schema change trên dev DB trước khi push lên production. + +--- + +*Last updated: 2026-01-25* diff --git a/release_v1.2.0.ps1 b/release_v1.2.0.ps1 deleted file mode 100644 index e681ae4..0000000 --- a/release_v1.2.0.ps1 +++ /dev/null @@ -1,24 +0,0 @@ -# release_v1.2.0.ps1 -Write-Host "🚧 Bắt đầu quy trình phát hành v1.2.0..." -ForegroundColor Cyan - -# 1. Kiểm tra trạng thái Git -git status - -# 2. Add tất cả thay đổi -Write-Host "📦 Đang đóng gói thay đổi..." -ForegroundColor Yellow -git add . - -# 3. Commit -Write-Host "📝 Đang tạo commit release..." -ForegroundColor Yellow -git commit -m "Release v1.2.0: Add Unsorted Stats, Security Fixes & Docker CI/CD" - -# 4. Tạo Tag -Write-Host "🏷️ Đang gắn thẻ v1.2.0..." -ForegroundColor Yellow -git tag v1.2.0 - -# 5. Push lên Github -Write-Host "🚀 Đang đẩy code và tags lên Github..." -ForegroundColor Green -git push origin main --tags - -Write-Host "✅ Hoàn tất! Github Actions sẽ tự động build Docker Image." -ForegroundColor Green -Write-Host "👉 Kiểm tra tiến độ tại: https://github.com/$(git config --get remote.origin.url | Split-Path -Leaf | ForEach-Object { $_ -replace '\.git$','' })/actions" diff --git a/release_v1.2.1.ps1 b/release_v1.2.1.ps1 deleted file mode 100644 index 3e57d70..0000000 --- a/release_v1.2.1.ps1 +++ /dev/null @@ -1,15 +0,0 @@ -# release_v1.2.1.ps1 -Write-Host "🛠️ Bắt đầu phát hành bản vá v1.2.1 (Fix CI)..." -ForegroundColor Cyan - -# Cấu hình Git user (đề phòng chưa có) -git config user.name "duongcamcute" -git config user.email "duongcamcute@users.noreply.github.com" - -# Git commands sequence -git add . -git commit -m "Fix: Configure Docker Buildx for Github Actions" -git tag v1.2.1 -git push origin main --tags - -Write-Host "✅ Đã đẩy v1.2.1 lên Github." -ForegroundColor Green -Write-Host "👉 Github Actions sẽ chạy lại ngay bây giờ. Vui lòng kiểm tra tab Actions." diff --git a/release_v1.2.2.ps1 b/release_v1.2.2.ps1 deleted file mode 100644 index 46e4ceb..0000000 --- a/release_v1.2.2.ps1 +++ /dev/null @@ -1,15 +0,0 @@ -# release_v1.2.2.ps1 -Write-Host "🚧 Phát hành bản vá v1.2.2 (Fix Login HTTP)..." -ForegroundColor Cyan - -# Git commands -git config user.name "duongcamcute" -git config user.email "duongcamcute@users.noreply.github.com" - -git add . -git commit -m "Fix: Allow insecure cookies for HTTP self-hosting" -git tag v1.2.2 -git push origin main --tags - -Write-Host "✅ Đã đẩy v1.2.2 lên Github." -ForegroundColor Green -Write-Host "👉 Vui lòng đợi Github Action build xong image mới." -Write-Host "⚠️ Quan Trọng: Bạn cần cập nhật lại file docker-compose.yml trên Unraid (thêm dòng DISABLE_SECURE_COOKIES=true)."