From 0f154e78bf8f1b93dc4871678c5e4a24b3079736 Mon Sep 17 00:00:00 2001 From: dash <1549469775@qq.com> Date: Sat, 22 Nov 2025 15:17:02 +0800 Subject: [PATCH] Enhance deployment process and project structure. Added deployment scripts for Windows and Linux, a comprehensive deployment guide, and Docker support. Updated .gitignore to include additional files and directories. Introduced PM2 configuration for process management and health checks for backend and frontend ser --- .gitignore | 45 +++++- DEPLOY.md | 366 +++++++++++++++++++++++++++++++++++++++++++++++++ DEPLOYMENT-GUIDE.md | 264 +++++++++++++++++++++++++++++++++++ README.md | 61 ++++++++- backend/.dockerignore | 17 +++ backend/Dockerfile | 51 +++++++ deploy.ps1 | 93 +++++++++++++ deploy.sh | 99 +++++++++++++ docker-compose.yml | 48 +++++++ docker-deploy.sh | 75 ++++++++++ docker-test.bat | 56 ++++++++ docker-test.sh | 53 +++++++ ecosystem.config.js | 50 +++++++ frontend/.dockerignore | 14 ++ frontend/Dockerfile | 42 ++++++ nginx.conf | 72 ++++++++++ package.json | 9 +- 17 files changed, 1400 insertions(+), 15 deletions(-) create mode 100644 DEPLOY.md create mode 100644 DEPLOYMENT-GUIDE.md create mode 100644 backend/.dockerignore create mode 100644 backend/Dockerfile create mode 100644 deploy.ps1 create mode 100644 deploy.sh create mode 100644 docker-compose.yml create mode 100644 docker-deploy.sh create mode 100644 docker-test.bat create mode 100644 docker-test.sh create mode 100644 ecosystem.config.js create mode 100644 frontend/.dockerignore create mode 100644 frontend/Dockerfile create mode 100644 nginx.conf diff --git a/.gitignore b/.gitignore index 47eed78..c4ef4dc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,45 @@ +# 依赖 node_modules/ +pnpm-lock.yaml + +# 构建产物 dist/ -*.log +build/ + +# 环境变量 .env -.DS_Store -database/*.sqlite3 -uploads/ +.env.local +.env.production +.env.development + +# 日志 +logs/ +*.log +npm-debug.log* +pnpm-debug.log* + +# 数据库 +*.sqlite3 +*.sqlite +*.db + +# PM2 +.pm2/ + +# IDE .vscode/ .idea/ -backup/ -*.zip +*.swp +*.swo +*~ + +# 系统文件 +.DS_Store +Thumbs.db + +# 上传文件 +uploads/ +# 临时文件 +tmp/ +temp/ diff --git a/DEPLOY.md b/DEPLOY.md new file mode 100644 index 0000000..9ad7ddf --- /dev/null +++ b/DEPLOY.md @@ -0,0 +1,366 @@ +# 部署指南 + +本项目提供多种部署方式,推荐使用 **PM2 一键部署**,简单快捷。 + +## 🚀 方案一:PM2 一键部署(推荐) + +最简单的部署方式,适合 VPS、云服务器等场景。 + +### Windows 部署 + +```powershell +# 1. 运行部署脚本 +.\deploy.ps1 +``` + +### Linux/macOS 部署 + +```bash +# 1. 添加执行权限 +chmod +x deploy.sh + +# 2. 运行部署脚本 +./deploy.sh +``` + +### 部署脚本会自动完成: + +1. ✅ 检查并安装必要工具(Node.js、pnpm、PM2) +2. ✅ 安装项目依赖 +3. ✅ 构建前后端项目 +4. ✅ 创建生产环境配置 +5. ✅ 运行数据库迁移 +6. ✅ 使用 PM2 启动服务 +7. ✅ 配置开机自启动 + +### 常用命令 + +```bash +# 查看服务状态 +pm2 status + +# 查看日志 +pm2 logs + +# 查看指定服务日志 +pm2 logs just-demo-backend +pm2 logs just-demo-frontend + +# 重启服务 +pm2 restart all +pm2 restart just-demo-backend + +# 停止服务 +pm2 stop all + +# 删除服务 +pm2 delete all +``` + +### 访问地址 + +部署成功后,可通过以下地址访问: + +- 前端:http://localhost:5500 +- 后端:http://localhost:3000 + +--- + +## 🐳 方案二:Docker Compose 部署 + +适合需要容器化部署的场景。 + +### 1. 创建 Dockerfile + +**backend/Dockerfile:** + +```dockerfile +FROM node:18-alpine + +WORKDIR /app + +# 安装 pnpm +RUN npm install -g pnpm + +# 复制依赖文件 +COPY package.json pnpm-lock.yaml ./ + +# 安装依赖 +RUN pnpm install --prod + +# 复制构建产物 +COPY dist ./dist +COPY database ./database +COPY knexfile.js ./ + +# 创建上传目录 +RUN mkdir -p uploads + +EXPOSE 3000 + +CMD ["node", "dist/app.js"] +``` + +**frontend/Dockerfile:** + +```dockerfile +FROM node:18-alpine + +WORKDIR /app + +# 安装 serve +RUN npm install -g serve + +# 复制构建产物 +COPY dist ./dist + +EXPOSE 5500 + +CMD ["serve", "dist", "-p", "5500", "-s"] +``` + +### 2. 创建 docker-compose.yml + +```yaml +version: '3.8' + +services: + backend: + build: + context: ./backend + dockerfile: Dockerfile + ports: + - "3000:3000" + environment: + - NODE_ENV=production + - PORT=3000 + - JWT_SECRET=${JWT_SECRET} + - FRONTEND_URL=http://localhost:5500 + volumes: + - ./backend/database:/app/database + - ./backend/uploads:/app/uploads + restart: always + + frontend: + build: + context: ./frontend + dockerfile: Dockerfile + ports: + - "5500:5500" + depends_on: + - backend + restart: always +``` + +### 3. 部署 + +```bash +# 构建项目 +pnpm build + +# 启动容器 +docker-compose up -d + +# 查看日志 +docker-compose logs -f + +# 停止容器 +docker-compose down +``` + +--- + +## ☁️ 方案三:云平台部署 + +### 3.1 Vercel + Railway + +**前端部署到 Vercel:** + +1. 在 Vercel 导入项目 +2. 设置构建配置: + - Build Command: `cd frontend && pnpm install && pnpm build` + - Output Directory: `frontend/dist` + +**后端部署到 Railway:** + +1. 在 Railway 创建新项目 +2. 连接 GitHub 仓库 +3. 设置环境变量: + ``` + NODE_ENV=production + PORT=3000 + JWT_SECRET=your-secret-key + FRONTEND_URL=your-vercel-url + ``` + +### 3.2 Render + +1. 在 Render 创建 Web Service +2. 后端配置: + - Build Command: `cd backend && pnpm install && pnpm build` + - Start Command: `cd backend && node dist/app.js` +3. 前端配置: + - Build Command: `cd frontend && pnpm install && pnpm build` + - Publish Directory: `frontend/dist` + +--- + +## 📝 生产环境配置 + +### 必要的环境变量 + +在 `backend/.env` 文件中配置: + +```env +NODE_ENV=production +PORT=3000 +JWT_SECRET=你的超级密钥-至少32字符 +FRONTEND_URL=http://your-frontend-domain.com +UPLOAD_DIR=uploads +``` + +### 生成安全的 JWT_SECRET + +```bash +# Linux/macOS +openssl rand -base64 32 + +# Windows PowerShell +[Convert]::ToBase64String((1..32 | ForEach-Object { Get-Random -Maximum 256 })) +``` + +--- + +## 🔒 安全建议 + +1. **修改 JWT_SECRET**:不要使用默认密钥 +2. **配置 HTTPS**:使用 nginx + Let's Encrypt +3. **限制文件上传大小**:防止恶意上传 +4. **定期备份数据库**:备份 `backend/database/*.sqlite3` +5. **配置防火墙**:只开放必要端口 + +--- + +## 🌐 使用 Nginx 反向代理(可选) + +### 安装 Nginx + +```bash +# Ubuntu/Debian +sudo apt update +sudo apt install nginx + +# CentOS/RHEL +sudo yum install nginx +``` + +### 配置文件 + +创建 `/etc/nginx/sites-available/just-demo`: + +```nginx +server { + listen 80; + server_name your-domain.com; + + # 前端 + location / { + proxy_pass http://localhost:5500; + 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; + } + + # 后端 API + location /api { + proxy_pass http://localhost:3000; + 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; + } +} +``` + +### 启用配置 + +```bash +sudo ln -s /etc/nginx/sites-available/just-demo /etc/nginx/sites-enabled/ +sudo nginx -t +sudo systemctl reload nginx +``` + +--- + +## 🔧 故障排查 + +### 服务无法启动 + +```bash +# 查看详细日志 +pm2 logs --lines 100 + +# 检查端口占用 +# Linux/macOS +lsof -i :3000 + +# Windows +netstat -ano | findstr :3000 +``` + +### 数据库错误 + +```bash +# 重新运行迁移 +cd backend +pnpm migrate:rollback:prod +pnpm migrate:prod +``` + +### 前端无法访问后端 + +检查 `backend/.env` 中的 `FRONTEND_URL` 配置是否正确。 + +--- + +## 📊 性能优化 + +1. **启用 PM2 集群模式**:充分利用多核 CPU +2. **配置 Nginx 缓存**:加快静态资源访问 +3. **使用 CDN**:加速前端资源加载 +4. **定期清理日志**:防止日志文件过大 + +--- + +## 🔄 更新部署 + +```bash +# 1. 拉取最新代码 +git pull + +# 2. 重新构建 +pnpm build + +# 3. 重启服务 +pm2 restart all + +# 或使用部署脚本 +./deploy.sh +``` + +--- + +## 📞 技术支持 + +如遇问题,请检查: +1. Node.js 版本是否 >= 16 +2. 端口 3000 和 5500 是否被占用 +3. 数据库文件是否有读写权限 +4. 环境变量是否配置正确 + diff --git a/DEPLOYMENT-GUIDE.md b/DEPLOYMENT-GUIDE.md new file mode 100644 index 0000000..8fa180b --- /dev/null +++ b/DEPLOYMENT-GUIDE.md @@ -0,0 +1,264 @@ +# 部署方案快速对比 + +选择最适合你的部署方式 🚀 + +## 📊 方案对比 + +| 方案 | 难度 | 适用场景 | 优点 | 缺点 | +|------|------|---------|------|------| +| **PM2 一键部署** ⭐推荐 | ⭐ 简单 | VPS、云服务器 | 最简单、一键部署、进程管理 | 需要服务器 | +| **Docker Compose** | ⭐⭐ 中等 | 容器化需求 | 环境隔离、易迁移 | 需要学习 Docker | +| **云平台部署** | ⭐ 简单 | 快速上线 | 免费额度、自动扩展 | 可能有费用 | +| **传统部署** | ⭐⭐⭐ 复杂 | 完全自定义 | 完全控制 | 配置复杂 | + +--- + +## 🎯 方案一:PM2 一键部署(最简单) + +### 适用场景 +- ✅ 你有一台 VPS 或云服务器 +- ✅ 想要最快速的部署方式 +- ✅ 需要进程管理和自动重启 +- ✅ 想要开机自启动 + +### 部署步骤 + +#### Windows +```powershell +# 一行命令搞定 +.\deploy.ps1 +``` + +#### Linux/macOS +```bash +# 一行命令搞定 +chmod +x deploy.sh && ./deploy.sh +``` + +### 特点 +- ⚡ **部署时间**: 3-5 分钟 +- 🎯 **一键完成**: 自动安装、构建、启动 +- 🔄 **自动重启**: 崩溃自动恢复 +- 📊 **进程监控**: PM2 提供完整的监控 +- 🚀 **开机自启**: 服务器重启自动启动 + +### 访问地址 +- 前端:`http://你的服务器IP:5500` +- 后端:`http://你的服务器IP:3000` + +--- + +## 🐳 方案二:Docker 部署 + +### 适用场景 +- ✅ 需要环境隔离 +- ✅ 多个项目部署 +- ✅ 需要容器编排 +- ✅ 跨平台部署 + +### 部署步骤 + +```bash +# 一键 Docker 部署 +chmod +x docker-deploy.sh && ./docker-deploy.sh + +# 或手动部署 +docker-compose up -d +``` + +### 特点 +- ⚡ **部署时间**: 5-10 分钟(首次构建) +- 📦 **环境隔离**: 不污染宿主机环境 +- 🔧 **易迁移**: 可在任何支持 Docker 的环境运行 +- 🔄 **自动重启**: 容器崩溃自动恢复 + +--- + +## ☁️ 方案三:云平台部署 + +### 3.1 Vercel(前端)+ Railway(后端) + +#### 前端部署到 Vercel +1. Fork/导入项目到 GitHub +2. 在 Vercel 导入仓库 +3. 配置构建: + ``` + Root Directory: frontend + Build Command: pnpm install && pnpm build + Output Directory: dist + ``` + +#### 后端部署到 Railway +1. 在 Railway 创建新项目 +2. 连接 GitHub 仓库 +3. 设置环境变量(自动生成) +4. 自动部署 + +### 特点 +- ⚡ **部署时间**: 5-10 分钟 +- 💰 **免费额度**: 都有免费版本 +- 🌍 **全球 CDN**: 访问速度快 +- 🔄 **自动部署**: Git push 自动部署 + +--- + +### 3.2 Render(All-in-One) + +#### 一站式部署 +1. 注册 Render 账号 +2. 连接 GitHub 仓库 +3. 创建两个 Web Services: + - **Backend**: + - Build: `cd backend && pnpm install && pnpm build` + - Start: `cd backend && node dist/app.js` + - **Frontend**: + - Build: `cd frontend && pnpm install && pnpm build` + - Static Site + - Publish: `frontend/dist` + +### 特点 +- ⚡ **部署时间**: 10-15 分钟 +- 💰 **免费计划**: 每月有免费额度 +- 🔄 **自动部署**: Git push 触发 +- 🔒 **免费 SSL**: 自动配置 HTTPS + +--- + +## 🎮 方案四:手动部署 + +### 适用场景 +- ✅ 需要完全自定义配置 +- ✅ 学习部署流程 +- ✅ 特殊环境要求 + +### 部署步骤 + +```bash +# 1. 克隆项目 +git clone +cd just-demo + +# 2. 安装依赖 +pnpm install:all + +# 3. 构建 +pnpm build + +# 4. 配置环境变量 +cp backend/.env.example backend/.env +# 编辑 backend/.env + +# 5. 数据库迁移 +cd backend && pnpm migrate:prod && cd .. + +# 6. 启动后端 +cd backend && node dist/app.js & + +# 7. 启动前端 +cd frontend && npx serve dist -p 5500 & +``` + +--- + +## 🔧 配置 Nginx 反向代理(可选) + +如果你使用 PM2 或手动部署,可以配置 Nginx: + +```bash +# 1. 安装 Nginx +sudo apt install nginx # Ubuntu/Debian + +# 2. 配置 +sudo cp nginx.conf /etc/nginx/sites-available/just-demo +sudo ln -s /etc/nginx/sites-available/just-demo /etc/nginx/sites-enabled/ + +# 3. 修改域名 +sudo nano /etc/nginx/sites-available/just-demo +# 将 your-domain.com 改为你的域名 + +# 4. 重启 Nginx +sudo nginx -t +sudo systemctl reload nginx +``` + +--- + +## 📱 快速决策指南 + +### 我该选哪个方案? + +#### 🏃 我想最快部署 +→ **选择 PM2 一键部署** +```bash +# Windows +.\deploy.ps1 + +# Linux/macOS +./deploy.sh +``` + +#### 💰 我没有服务器/想省钱 +→ **选择云平台部署** +- Vercel(前端免费) +- Railway(后端有免费额度) +- Render(全栈免费) + +#### 🐳 我想要容器化 +→ **选择 Docker 部署** +```bash +./docker-deploy.sh +``` + +#### 🎓 我想学习部署流程 +→ **选择手动部署** +- 完整了解每个步骤 +- 便于排查问题 + +--- + +## 🆘 遇到问题? + +### PM2 方案 +```bash +pm2 logs # 查看日志 +pm2 status # 查看状态 +pm2 restart all # 重启服务 +``` + +### Docker 方案 +```bash +docker-compose logs -f # 查看日志 +docker-compose ps # 查看状态 +docker-compose restart # 重启服务 +``` + +### 云平台 +- 查看部署日志 +- 检查环境变量 +- 查看服务状态 + +--- + +## 📚 详细文档 + +- [完整部署指南](./DEPLOY.md) +- [项目说明](./README.md) + +--- + +## 🎉 开始部署 + +选择一个方案,立即开始: + +```bash +# PM2(推荐) +./deploy.sh # Linux/macOS +.\deploy.ps1 # Windows + +# Docker +./docker-deploy.sh + +# 查看详细文档 +cat DEPLOY.md +``` + diff --git a/README.md b/README.md index ac0add8..9f51119 100644 --- a/README.md +++ b/README.md @@ -11,16 +11,13 @@ ## 快速开始 -### 安装依赖 +### 开发环境 ```bash +# 1. 安装依赖 pnpm install:all -``` - -### 开发 -```bash -# 同时启动前后端 +# 2. 启动开发服务器 pnpm dev # 或分别启动 @@ -28,12 +25,62 @@ pnpm dev:backend # 后端:http://localhost:3000 pnpm dev:frontend # 前端:http://localhost:5173 ``` -### 构建 +### 生产部署 🚀 + +#### 一键部署(推荐) + +**Windows:** +```powershell +.\deploy.ps1 +``` + +**Linux/macOS:** +```bash +chmod +x deploy.sh +./deploy.sh +``` + +部署脚本会自动完成: +- ✅ 检查并安装必要工具(Node.js、pnpm、PM2) +- ✅ 安装项目依赖 +- ✅ 构建前后端项目 +- ✅ 创建生产环境配置 +- ✅ 运行数据库迁移 +- ✅ 使用 PM2 启动服务 +- ✅ 配置开机自启动 + +部署成功后访问: +- 前端:http://localhost:5500 +- 后端:http://localhost:3000 + +#### 手动部署 ```bash +# 1. 构建项目 pnpm build + +# 2. 创建环境配置 +cp backend/.env.example backend/.env +# 编辑 backend/.env 修改配置 + +# 3. 运行数据库迁移 +cd backend && pnpm migrate:prod && cd .. + +# 4. 启动服务 +pnpm start ``` +#### 常用命令 + +```bash +pm2 status # 查看服务状态 +pm2 logs # 查看日志 +pm2 restart all # 重启服务 +pm2 stop all # 停止服务 +``` + +📖 详细部署说明请查看 [DEPLOY.md](./DEPLOY.md) + ## 项目结构 ``` diff --git a/backend/.dockerignore b/backend/.dockerignore new file mode 100644 index 0000000..a709a01 --- /dev/null +++ b/backend/.dockerignore @@ -0,0 +1,17 @@ +node_modules +npm-debug.log +pnpm-debug.log +dist +build +.git +.gitignore +*.md +.env +.env.local +.vscode +.idea +*.log +uploads +database/*.sqlite3 +database/*.db + diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..03c7f7d --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,51 @@ +FROM node:18-alpine AS builder + +WORKDIR /app + +# 安装 pnpm +RUN npm install -g pnpm + +# 复制依赖文件 +COPY package.json pnpm-lock.yaml ./ + +# 安装依赖 +RUN pnpm install --frozen-lockfile + +# 复制源代码 +COPY . . + +# 构建 +RUN pnpm build + +# 生产阶段 +FROM node:18-alpine + +WORKDIR /app + +# 安装必要工具 +RUN apk add --no-cache wget && \ + npm install -g pnpm + +# 只安装生产依赖 +COPY package.json pnpm-lock.yaml ./ +RUN pnpm install --prod --frozen-lockfile + +# 复制构建产物和必要文件 +COPY --from=builder /app/dist ./dist +COPY knexfile.js ./ + +# 创建必要的目录 +RUN mkdir -p uploads database && \ + chown -R node:node /app + +# 使用非 root 用户 +USER node + +EXPOSE 3000 + +# 健康检查 +HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ + CMD wget --quiet --tries=1 --spider http://localhost:3000/api/health || exit 1 + +CMD ["node", "dist/app.js"] + diff --git a/deploy.ps1 b/deploy.ps1 new file mode 100644 index 0000000..125cedf --- /dev/null +++ b/deploy.ps1 @@ -0,0 +1,93 @@ +# 一键部署脚本 - Windows PowerShell +# 使用方法: .\deploy.ps1 + +$ErrorActionPreference = "Stop" + +Write-Host "🚀 开始部署 Just-Demo 项目..." -ForegroundColor Cyan + +# 1. 检查 Node.js +Write-Host "`n📦 检查 Node.js..." -ForegroundColor Blue +if (-not (Get-Command node -ErrorAction SilentlyContinue)) { + Write-Host "❌ Node.js 未安装,请先安装 Node.js (v16+)" -ForegroundColor Red + Write-Host "下载地址: https://nodejs.org/" -ForegroundColor Yellow + exit 1 +} +Write-Host "✅ Node.js 版本: $(node -v)" -ForegroundColor Green + +# 2. 检查 pnpm,如果没有则安装 +Write-Host "`n📦 检查 pnpm..." -ForegroundColor Blue +if (-not (Get-Command pnpm -ErrorAction SilentlyContinue)) { + Write-Host "pnpm 未安装,正在安装..." -ForegroundColor Yellow + npm install -g pnpm +} +Write-Host "✅ pnpm 版本: $(pnpm -v)" -ForegroundColor Green + +# 3. 检查 PM2,如果没有则安装 +Write-Host "`n📦 检查 PM2..." -ForegroundColor Blue +if (-not (Get-Command pm2 -ErrorAction SilentlyContinue)) { + Write-Host "PM2 未安装,正在安装..." -ForegroundColor Yellow + npm install -g pm2 + npm install -g pm2-windows-startup + pm2-startup install +} +Write-Host "✅ PM2 已安装" -ForegroundColor Green + +# 4. 安装依赖 +Write-Host "`n📦 安装项目依赖..." -ForegroundColor Blue +pnpm install:all + +# 5. 构建项目 +Write-Host "`n🔨 构建项目..." -ForegroundColor Blue +pnpm build + +# 6. 创建生产环境配置 +Write-Host "`n⚙️ 创建生产环境配置..." -ForegroundColor Blue +if (-not (Test-Path "backend\.env")) { + # 生成随机密钥 + $bytes = New-Object byte[] 32 + $rng = [System.Security.Cryptography.RandomNumberGenerator]::Create() + $rng.GetBytes($bytes) + $jwtSecret = [Convert]::ToBase64String($bytes) + + @" +NODE_ENV=production +PORT=3000 +JWT_SECRET=$jwtSecret +FRONTEND_URL=http://localhost:5500 +UPLOAD_DIR=uploads +"@ | Out-File -FilePath "backend\.env" -Encoding UTF8 + Write-Host "✅ 已创建 backend\.env" -ForegroundColor Green +} else { + Write-Host "✅ backend\.env 已存在" -ForegroundColor Green +} + +# 7. 运行数据库迁移 +Write-Host "`n🗄️ 运行数据库迁移..." -ForegroundColor Blue +Set-Location backend +pnpm migrate:prod +Set-Location .. + +# 8. 使用 PM2 启动服务 +Write-Host "`n🚀 使用 PM2 启动服务..." -ForegroundColor Blue +pm2 delete just-demo-backend 2>$null +pm2 start ecosystem.config.js + +# 9. 保存 PM2 配置 +Write-Host "`n💾 保存 PM2 配置..." -ForegroundColor Blue +pm2 save + +# 10. 显示服务状态 +Write-Host "`n📊 服务状态:" -ForegroundColor Cyan +pm2 status + +Write-Host "`n🎉 部署成功!" -ForegroundColor Green +Write-Host "`n访问地址:" -ForegroundColor Cyan +Write-Host " - 前端: http://localhost:5500" -ForegroundColor White +Write-Host " - 后端: http://localhost:3000" -ForegroundColor White +Write-Host "`n常用命令:" -ForegroundColor Cyan +Write-Host " pm2 status # 查看服务状态" -ForegroundColor White +Write-Host " pm2 logs # 查看日志" -ForegroundColor White +Write-Host " pm2 restart all # 重启所有服务" -ForegroundColor White +Write-Host " pm2 stop all # 停止所有服务" -ForegroundColor White +Write-Host "" + diff --git a/deploy.sh b/deploy.sh new file mode 100644 index 0000000..74bb5dd --- /dev/null +++ b/deploy.sh @@ -0,0 +1,99 @@ +#!/bin/bash + +# 一键部署脚本 - Linux/macOS +# 使用方法: chmod +x deploy.sh && ./deploy.sh + +set -e # 遇到错误立即退出 + +echo "🚀 开始部署 Just-Demo 项目..." + +# 颜色定义 +GREEN='\033[0;32m' +BLUE='\033[0;34m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +# 1. 检查 Node.js +echo -e "${BLUE}📦 检查 Node.js...${NC}" +if ! command -v node &> /dev/null; then + echo -e "${RED}❌ Node.js 未安装,请先安装 Node.js (v16+)${NC}" + exit 1 +fi +echo -e "${GREEN}✅ Node.js 版本: $(node -v)${NC}" + +# 2. 检查 pnpm,如果没有则安装 +echo -e "${BLUE}📦 检查 pnpm...${NC}" +if ! command -v pnpm &> /dev/null; then + echo "pnpm 未安装,正在安装..." + npm install -g pnpm +fi +echo -e "${GREEN}✅ pnpm 版本: $(pnpm -v)${NC}" + +# 3. 检查 PM2,如果没有则安装 +echo -e "${BLUE}📦 检查 PM2...${NC}" +if ! command -v pm2 &> /dev/null; then + echo "PM2 未安装,正在安装..." + npm install -g pm2 +fi +echo -e "${GREEN}✅ PM2 已安装${NC}" + +# 4. 安装依赖 +echo -e "${BLUE}📦 安装项目依赖...${NC}" +pnpm install:all + +# 5. 构建项目 +echo -e "${BLUE}🔨 构建项目...${NC}" +pnpm build + +# 6. 创建生产环境配置 +echo -e "${BLUE}⚙️ 创建生产环境配置...${NC}" +if [ ! -f backend/.env ]; then + cat > backend/.env << EOF +NODE_ENV=production +PORT=3000 +JWT_SECRET=$(openssl rand -base64 32) +FRONTEND_URL=http://localhost:5500 +UPLOAD_DIR=uploads +EOF + echo -e "${GREEN}✅ 已创建 backend/.env${NC}" +else + echo -e "${GREEN}✅ backend/.env 已存在${NC}" +fi + +# 7. 运行数据库迁移 +echo -e "${BLUE}🗄️ 运行数据库迁移...${NC}" +cd backend +pnpm migrate:prod +cd .. + +# 8. 使用 PM2 启动服务 +echo -e "${BLUE}🚀 使用 PM2 启动服务...${NC}" +pm2 delete just-demo-backend 2>/dev/null || true +pm2 start ecosystem.config.js + +# 9. 保存 PM2 配置(开机自启动) +echo -e "${BLUE}💾 配置 PM2 开机自启动...${NC}" +pm2 save +pm2 startup + +# 10. 显示服务状态 +echo "" +echo -e "${GREEN}✅ 部署完成!${NC}" +echo "" +echo "📊 服务状态:" +pm2 status + +echo "" +echo -e "${GREEN}🎉 部署成功!${NC}" +echo "" +echo "访问地址:" +echo " - 前端: http://localhost:5500" +echo " - 后端: http://localhost:3000" +echo "" +echo "常用命令:" +echo " pm2 status # 查看服务状态" +echo " pm2 logs # 查看日志" +echo " pm2 restart all # 重启所有服务" +echo " pm2 stop all # 停止所有服务" +echo "" + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..6dc1840 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,48 @@ +version: '3.8' + +services: + backend: + build: + context: ./backend + dockerfile: Dockerfile + container_name: just-demo-backend + ports: + - "3000:3000" + environment: + - NODE_ENV=production + - PORT=3000 + - JWT_SECRET=${JWT_SECRET:-your-secret-key-please-change} + - FRONTEND_URL=${FRONTEND_URL:-http://localhost:5500} + - UPLOAD_DIR=uploads + volumes: + - ./backend/database:/app/database + - ./backend/uploads:/app/uploads + restart: unless-stopped + healthcheck: + test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3000/api/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + frontend: + build: + context: ./frontend + dockerfile: Dockerfile + container_name: just-demo-frontend + ports: + - "5500:5500" + depends_on: + - backend + restart: unless-stopped + healthcheck: + test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:5500"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 20s + +networks: + default: + name: just-demo-network + diff --git a/docker-deploy.sh b/docker-deploy.sh new file mode 100644 index 0000000..221c2f9 --- /dev/null +++ b/docker-deploy.sh @@ -0,0 +1,75 @@ +#!/bin/bash + +# Docker 一键部署脚本 +# 使用方法: chmod +x docker-deploy.sh && ./docker-deploy.sh + +set -e + +echo "🐳 开始 Docker 部署..." + +# 颜色定义 +GREEN='\033[0;32m' +BLUE='\033[0;34m' +RED='\033[0;31m' +NC='\033[0m' + +# 1. 检查 Docker +echo -e "${BLUE}📦 检查 Docker...${NC}" +if ! command -v docker &> /dev/null; then + echo -e "${RED}❌ Docker 未安装${NC}" + echo "请访问 https://docs.docker.com/get-docker/ 安装 Docker" + exit 1 +fi +echo -e "${GREEN}✅ Docker 版本: $(docker --version)${NC}" + +# 2. 检查 Docker Compose +echo -e "${BLUE}📦 检查 Docker Compose...${NC}" +if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then + echo -e "${RED}❌ Docker Compose 未安装${NC}" + exit 1 +fi +echo -e "${GREEN}✅ Docker Compose 已安装${NC}" + +# 3. 创建环境配置 +echo -e "${BLUE}⚙️ 创建环境配置...${NC}" +if [ ! -f .env ]; then + JWT_SECRET=$(openssl rand -base64 32) + cat > .env << EOF +JWT_SECRET=$JWT_SECRET +FRONTEND_URL=http://localhost:5500 +EOF + echo -e "${GREEN}✅ 已创建 .env${NC}" +else + echo -e "${GREEN}✅ .env 已存在${NC}" +fi + +# 4. 构建和启动容器 +echo -e "${BLUE}🔨 构建和启动容器...${NC}" +docker-compose down +docker-compose build --no-cache +docker-compose up -d + +# 5. 等待服务启动 +echo -e "${BLUE}⏳ 等待服务启动...${NC}" +sleep 5 + +# 6. 显示容器状态 +echo -e "${GREEN}✅ 部署完成!${NC}" +echo "" +echo "📊 容器状态:" +docker-compose ps + +echo "" +echo -e "${GREEN}🎉 部署成功!${NC}" +echo "" +echo "访问地址:" +echo " - 前端: http://localhost:5500" +echo " - 后端: http://localhost:3000" +echo "" +echo "常用命令:" +echo " docker-compose ps # 查看容器状态" +echo " docker-compose logs -f # 查看日志" +echo " docker-compose restart # 重启服务" +echo " docker-compose down # 停止服务" +echo "" + diff --git a/docker-test.bat b/docker-test.bat new file mode 100644 index 0000000..2a9f5a6 --- /dev/null +++ b/docker-test.bat @@ -0,0 +1,56 @@ +@echo off +echo 🐳 开始 Docker 构建测试... +echo. + +echo [1/4] 检查 Docker 环境... +docker --version >nul 2>&1 +if errorlevel 1 ( + echo ❌ Docker 未安装或未启动 + pause + exit /b 1 +) +echo ✅ Docker 已就绪 +echo. + +echo [2/4] 停止旧容器... +docker-compose down +echo. + +echo [3/4] 构建镜像(这可能需要几分钟)... +docker-compose build --no-cache +if errorlevel 1 ( + echo ❌ 构建失败 + pause + exit /b 1 +) +echo ✅ 构建成功 +echo. + +echo [4/4] 启动容器... +docker-compose up -d +if errorlevel 1 ( + echo ❌ 启动失败 + pause + exit /b 1 +) +echo. + +echo ⏳ 等待服务启动(10秒)... +timeout /t 10 /nobreak >nul +echo. + +echo 📊 容器状态: +docker-compose ps +echo. + +echo 🎉 部署完成! +echo. +echo 访问地址: +echo 前端: http://localhost:5500 +echo 后端: http://localhost:3000 +echo. +echo 查看日志: docker-compose logs -f +echo 停止服务: docker-compose down +echo. +pause + diff --git a/docker-test.sh b/docker-test.sh new file mode 100644 index 0000000..5358992 --- /dev/null +++ b/docker-test.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +# Docker 构建测试脚本 +echo "🐳 开始 Docker 构建测试..." +echo "" + +echo "[1/4] 检查 Docker 环境..." +if ! command -v docker &> /dev/null; then + echo "❌ Docker 未安装或未启动" + exit 1 +fi +echo "✅ Docker 已就绪" +echo "" + +echo "[2/4] 停止旧容器..." +docker-compose down +echo "" + +echo "[3/4] 构建镜像(这可能需要几分钟)..." +docker-compose build --no-cache +if [ $? -ne 0 ]; then + echo "❌ 构建失败" + exit 1 +fi +echo "✅ 构建成功" +echo "" + +echo "[4/4] 启动容器..." +docker-compose up -d +if [ $? -ne 0 ]; then + echo "❌ 启动失败" + exit 1 +fi +echo "" + +echo "⏳ 等待服务启动(10秒)..." +sleep 10 +echo "" + +echo "📊 容器状态:" +docker-compose ps +echo "" + +echo "🎉 部署完成!" +echo "" +echo "访问地址:" +echo " 前端: http://localhost:5500" +echo " 后端: http://localhost:3000" +echo "" +echo "查看日志: docker-compose logs -f" +echo "停止服务: docker-compose down" +echo "" + diff --git a/ecosystem.config.js b/ecosystem.config.js new file mode 100644 index 0000000..f8bff33 --- /dev/null +++ b/ecosystem.config.js @@ -0,0 +1,50 @@ +// PM2 配置文件 +module.exports = { + apps: [ + { + name: 'just-demo-backend', + script: './backend/dist/app.js', + cwd: './', + instances: 1, + autorestart: true, + watch: false, + max_memory_restart: '500M', + env: { + NODE_ENV: 'production', + PORT: 3000 + }, + env_production: { + NODE_ENV: 'production', + PORT: 3000 + }, + error_file: './logs/backend-error.log', + out_file: './logs/backend-out.log', + log_date_format: 'YYYY-MM-DD HH:mm:ss Z', + merge_logs: true, + // 自动重启策略 + min_uptime: '10s', + max_restarts: 10, + // 启动延迟 + listen_timeout: 3000, + kill_timeout: 5000 + }, + { + name: 'just-demo-frontend', + script: 'serve', + cwd: './frontend', + args: 'dist -p 5500 -s', + instances: 1, + autorestart: true, + watch: false, + max_memory_restart: '200M', + env: { + NODE_ENV: 'production' + }, + error_file: './logs/frontend-error.log', + out_file: './logs/frontend-out.log', + log_date_format: 'YYYY-MM-DD HH:mm:ss Z', + merge_logs: true + } + ] +}; + diff --git a/frontend/.dockerignore b/frontend/.dockerignore new file mode 100644 index 0000000..f7f87c2 --- /dev/null +++ b/frontend/.dockerignore @@ -0,0 +1,14 @@ +node_modules +npm-debug.log +pnpm-debug.log +dist +build +.git +.gitignore +*.md +.env +.env.local +.vscode +.idea +*.log + diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..fd8236d --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,42 @@ +FROM node:18-alpine AS builder + +WORKDIR /app + +# 安装 pnpm +RUN npm install -g pnpm + +# 复制依赖文件 +COPY package.json pnpm-lock.yaml ./ + +# 安装依赖 +RUN pnpm install --frozen-lockfile + +# 复制源代码 +COPY . . + +# 构建 +RUN pnpm build + +# 生产阶段 +FROM node:18-alpine + +WORKDIR /app + +# 安装必要工具 +RUN apk add --no-cache wget && \ + npm install -g serve + +# 复制构建产物 +COPY --from=builder /app/dist ./dist + +# 使用非 root 用户 +RUN chown -R node:node /app +USER node + +EXPOSE 5500 + +HEALTHCHECK --interval=30s --timeout=10s --start-period=20s --retries=3 \ + CMD wget --quiet --tries=1 --spider http://localhost:5500 || exit 1 + +CMD ["serve", "dist", "-p", "5500", "-s"] + diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..173f3fb --- /dev/null +++ b/nginx.conf @@ -0,0 +1,72 @@ +server { + listen 80; + server_name your-domain.com; # 修改为你的域名 + + # Gzip 压缩 + gzip on; + gzip_vary on; + gzip_min_length 1024; + gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/json; + + # 前端静态文件 + location / { + proxy_pass http://localhost:5500; + 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; + + # 缓存设置 + proxy_cache_valid 200 1d; + proxy_cache_bypass $http_upgrade; + add_header X-Cache-Status $upstream_cache_status; + } + + # 后端 API + location /api { + proxy_pass http://localhost:3000; + 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; + + # 超时设置 + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + } + + # 上传文件访问 + location /uploads { + proxy_pass http://localhost:3000/uploads; + proxy_http_version 1.1; + proxy_set_header Host $host; + + # 缓存上传的文件 + expires 30d; + add_header Cache-Control "public, immutable"; + } + + # 日志 + access_log /var/log/nginx/just-demo-access.log; + error_log /var/log/nginx/just-demo-error.log; +} + +# HTTPS 配置(使用 Let's Encrypt) +# server { +# listen 443 ssl http2; +# server_name your-domain.com; +# +# ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem; +# ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem; +# ssl_protocols TLSv1.2 TLSv1.3; +# ssl_ciphers HIGH:!aNULL:!MD5; +# +# # ... 其他配置同上 +# } + diff --git a/package.json b/package.json index 4430c80..e50b0d8 100644 --- a/package.json +++ b/package.json @@ -7,14 +7,19 @@ "dev": "concurrently \"pnpm run dev:backend\" \"pnpm run dev:frontend\"", "dev:backend": "cd backend && pnpm run dev", "dev:frontend": "cd frontend && pnpm run dev", - "start": "cd backend && pnpm run start:p", + "start": "pm2 start ecosystem.config.js", + "stop": "pm2 stop all", + "restart": "pm2 restart all", + "status": "pm2 status", + "logs": "pm2 logs", "build": "pnpm run build:backend && pnpm run build:frontend", "build:backend": "cd backend && pnpm run build", "build:frontend": "cd frontend && pnpm run build", "install:all": "pnpm install && cd backend && pnpm install && cd ../frontend && pnpm install" }, "devDependencies": { - "concurrently": "^8.2.2" + "concurrently": "^8.2.2", + "serve": "^14.2.1" } }