17 changed files with 1400 additions and 15 deletions
@ -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/ |
|||
|
|||
@ -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. 环境变量是否配置正确 |
|||
|
|||
@ -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 <your-repo> |
|||
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 |
|||
``` |
|||
|
|||
@ -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 |
|||
|
|||
@ -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"] |
|||
|
|||
@ -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 "" |
|||
|
|||
@ -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 "" |
|||
|
|||
@ -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 |
|||
|
|||
@ -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 "" |
|||
|
|||
@ -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 |
|||
|
|||
@ -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 "" |
|||
|
|||
@ -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 |
|||
} |
|||
] |
|||
}; |
|||
|
|||
@ -0,0 +1,14 @@ |
|||
node_modules |
|||
npm-debug.log |
|||
pnpm-debug.log |
|||
dist |
|||
build |
|||
.git |
|||
.gitignore |
|||
*.md |
|||
.env |
|||
.env.local |
|||
.vscode |
|||
.idea |
|||
*.log |
|||
|
|||
@ -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"] |
|||
|
|||
@ -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; |
|||
# |
|||
# # ... 其他配置同上 |
|||
# } |
|||
|
|||
Loading…
Reference in new issue