- 完整的前后端代码 - 支持本地存储和SFTP存储 - 文件分享功能 - 上传工具源代码 - 完整的部署文档 - Nginx配置模板 技术栈: - 后端: Node.js + Express + SQLite - 前端: Vue.js 3 + Axios - 存储: 本地存储 / SFTP远程存储
1212 lines
27 KiB
Markdown
1212 lines
27 KiB
Markdown
# 玩玩云 - Docker部署指南
|
||
|
||
> **📌 重要提示:代码自动适配域名**
|
||
>
|
||
> 本项目代码**完全支持域名动态适配**,无需修改任何代码:
|
||
> - ✅ 前端会自动使用当前访问的域名和协议(http/https)
|
||
> - ✅ 后端会从HTTP请求头动态获取域名信息
|
||
> - ✅ 上传工具配置文件会自动生成正确的API地址
|
||
>
|
||
> **您只需要:**
|
||
> 1. 配置宝塔/Nginx的反向代理指向Docker容器
|
||
> 2. 配置SSL证书(可选,推荐)
|
||
> 3. 启动Docker容器
|
||
>
|
||
> **无需修改代码中的任何域名或IP地址!**
|
||
|
||
## 目录
|
||
1. [系统要求](#系统要求)
|
||
2. [部署架构](#部署架构)
|
||
3. [快速部署步骤](#快速部署步骤)
|
||
4. [详细配置说明](#详细配置说明)
|
||
5. [常见问题解决](#常见问题解决)
|
||
6. [维护操作](#维护操作)
|
||
|
||
---
|
||
|
||
## 系统要求
|
||
|
||
### 服务器配置
|
||
- **操作系统**: Ubuntu 20.04+ / CentOS 7+ / Debian 10+
|
||
- **内存**: 最低 1GB RAM(推荐 2GB+)
|
||
- **磁盘**: 最低 10GB 可用空间
|
||
- **端口**: 需要开放以下端口
|
||
- `80` - HTTP (可选,用于重定向到HTTPS)
|
||
- `443` - HTTPS (SSL访问)
|
||
- `8080` - 内部HTTP端口(Docker容器)
|
||
- `40001` - 后端API端口(Docker容器)
|
||
|
||
### 软件依赖
|
||
- **Docker**: 20.10.0+
|
||
- **Docker Compose**: 2.0.0+
|
||
- **Git**: 用于代码管理(可选)
|
||
- **Nginx**: 宝塔面板或系统级Nginx(用于SSL终止和反向代理)
|
||
|
||
---
|
||
|
||
## 部署架构
|
||
|
||
```
|
||
互联网
|
||
↓
|
||
宝塔 Nginx (443 HTTPS) ← SSL证书在此层
|
||
↓
|
||
Docker Nginx (8080 HTTP) ← 前端静态文件
|
||
↓
|
||
Backend API (40001) ← Node.js + SQLite
|
||
↓
|
||
SFTP服务器 (用户自建)
|
||
```
|
||
|
||
### 容器架构
|
||
```
|
||
docker-compose.yml
|
||
├── frontend (nginx:alpine)
|
||
│ ├── 静态文件: /usr/share/nginx/html
|
||
│ ├── Nginx配置: /etc/nginx/conf.d/default.conf
|
||
│ └── 端口: 8080:80, 8443:443
|
||
│
|
||
├── backend (wanwanyun-backend)
|
||
│ ├── Node.js应用: /app
|
||
│ ├── 数据库: /app/users.db (SQLite)
|
||
│ ├── 上传工具: /upload-tool
|
||
│ └── 端口: 40001:40001
|
||
│
|
||
└── certbot (certbot/certbot)
|
||
└── SSL证书: /etc/letsencrypt (可选)
|
||
```
|
||
|
||
---
|
||
|
||
## 快速部署步骤
|
||
|
||
### 步骤1: 准备服务器环境
|
||
|
||
```bash
|
||
# 1. 安装Docker
|
||
curl -fsSL https://get.docker.com | sh
|
||
systemctl start docker
|
||
systemctl enable docker
|
||
|
||
# 2. 安装Docker Compose
|
||
curl -L "https://github.com/docker/compose/releases/download/v2.20.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
||
chmod +x /usr/local/bin/docker-compose
|
||
|
||
# 3. 验证安装
|
||
docker --version
|
||
docker-compose --version
|
||
```
|
||
|
||
### 步骤2: 上传项目文件
|
||
|
||
```bash
|
||
# 在服务器上创建项目目录
|
||
mkdir -p /var/www/wanwanyun
|
||
cd /var/www/wanwanyun
|
||
|
||
# 从本地上传所有文件(在本地执行)
|
||
scp -r C:/Users/Administrator/Desktop/ftp-web-manager/* root@YOUR_SERVER_IP:/var/www/wanwanyun/
|
||
```
|
||
|
||
或使用Git:
|
||
```bash
|
||
cd /var/www/wanwanyun
|
||
git clone YOUR_REPOSITORY_URL .
|
||
```
|
||
|
||
### 步骤3: 构建后端镜像
|
||
|
||
```bash
|
||
cd /var/www/wanwanyun
|
||
docker build -t wanwanyun-backend -f backend/Dockerfile .
|
||
```
|
||
|
||
**Dockerfile内容**(应该在 `backend/Dockerfile`):
|
||
```dockerfile
|
||
FROM node:18-alpine
|
||
|
||
WORKDIR /app
|
||
|
||
# 复制package.json和package-lock.json
|
||
COPY backend/package*.json ./
|
||
|
||
# 安装依赖
|
||
RUN npm install --production
|
||
|
||
# 复制应用代码
|
||
COPY backend/ ./
|
||
|
||
# 暴露端口
|
||
EXPOSE 40001
|
||
|
||
# 启动应用
|
||
CMD ["node", "server.js"]
|
||
```
|
||
|
||
### 步骤4: 启动容器
|
||
|
||
```bash
|
||
cd /var/www/wanwanyun
|
||
docker-compose up -d
|
||
|
||
# 查看容器状态
|
||
docker-compose ps
|
||
|
||
# 查看日志
|
||
docker-compose logs -f
|
||
```
|
||
|
||
### 步骤5: 配置宝塔Nginx(或系统Nginx)
|
||
|
||
#### 宝塔面板配置
|
||
|
||
1. **添加网站**
|
||
- 域名: `example.com`(替换为您的实际域名)
|
||
- 根目录: `/var/www/wanwanyun/frontend`(仅作为占位,实际不使用)
|
||
- PHP版本: 纯静态
|
||
|
||
2. **配置SSL证书**
|
||
- 在宝塔面板申请Let's Encrypt证书
|
||
- 或上传自有证书
|
||
|
||
3. **修改Nginx配置**
|
||
|
||
编辑网站配置文件(通常在 `/www/server/panel/vhost/nginx/您的域名.conf`):
|
||
|
||
```nginx
|
||
# HTTP重定向到HTTPS
|
||
server {
|
||
listen 80;
|
||
server_name example.com; # 替换为您的域名
|
||
return 301 https://$server_name$request_uri;
|
||
}
|
||
|
||
# HTTPS配置
|
||
server {
|
||
listen 443 ssl http2;
|
||
server_name example.com; # 替换为您的域名
|
||
|
||
# SSL证书路径(宝塔自动配置)
|
||
ssl_certificate /www/server/panel/vhost/cert/example.com/fullchain.pem;
|
||
ssl_certificate_key /www/server/panel/vhost/cert/example.com/privkey.pem;
|
||
|
||
ssl_protocols TLSv1.2 TLSv1.3;
|
||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||
ssl_prefer_server_ciphers on;
|
||
|
||
# 反向代理到Docker容器
|
||
location / {
|
||
proxy_pass http://127.0.0.1:8080;
|
||
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_http_version 1.1;
|
||
proxy_set_header Upgrade $http_upgrade;
|
||
proxy_set_header Connection "upgrade";
|
||
}
|
||
|
||
# API反向代理
|
||
location /api/ {
|
||
proxy_pass http://127.0.0.1:8080;
|
||
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;
|
||
}
|
||
|
||
# 分享链接
|
||
location /s/ {
|
||
proxy_pass http://127.0.0.1:8080;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
}
|
||
|
||
# 访问日志
|
||
access_log /www/wwwlogs/example.com.log;
|
||
error_log /www/wwwlogs/example.com.error.log;
|
||
}
|
||
```
|
||
|
||
4. **重载Nginx**
|
||
```bash
|
||
nginx -t # 测试配置
|
||
nginx -s reload # 重载配置
|
||
```
|
||
|
||
#### 系统Nginx配置(无宝塔)
|
||
|
||
配置文件位置: `/etc/nginx/sites-available/wanwanyun.conf`
|
||
|
||
```nginx
|
||
# 与上述配置相同,但SSL证书路径可能不同
|
||
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
|
||
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
|
||
```
|
||
|
||
创建软链接并重载:
|
||
```bash
|
||
ln -s /etc/nginx/sites-available/wanwanyun.conf /etc/nginx/sites-enabled/
|
||
nginx -t
|
||
systemctl reload nginx
|
||
```
|
||
|
||
### 步骤6: 验证部署
|
||
|
||
1. **访问网站**
|
||
```
|
||
https://example.com # 替换为您的域名
|
||
```
|
||
|
||
2. **默认管理员账号**
|
||
- 首次启动会自动创建:
|
||
- 用户名: `admin`
|
||
- 密码: `admin123`
|
||
- ⚠️ **登录后请立即修改密码!**
|
||
|
||
3. **测试功能**
|
||
- ✓ 登录/注册
|
||
- ✓ SFTP配置
|
||
- ✓ 文件列表
|
||
- ✓ 文件上传/下载
|
||
- ✓ 文件分享
|
||
- ✓ 下载上传工具
|
||
|
||
---
|
||
|
||
## 详细配置说明
|
||
|
||
### 1. docker-compose.yml 配置
|
||
|
||
```yaml
|
||
version: '3.8'
|
||
|
||
services:
|
||
backend:
|
||
image: wanwanyun-backend
|
||
container_name: wanwanyun-backend
|
||
restart: always
|
||
ports:
|
||
- "40001:40001"
|
||
volumes:
|
||
- ./backend:/app
|
||
- /app/node_modules
|
||
- ./upload-tool:/upload-tool # 上传工具目录
|
||
environment:
|
||
- NODE_ENV=production
|
||
networks:
|
||
- wanwanyun-network
|
||
|
||
frontend:
|
||
image: nginx:alpine
|
||
container_name: wanwanyun-frontend
|
||
restart: always
|
||
ports:
|
||
- "8080:80" # HTTP端口
|
||
- "8443:443" # HTTPS端口(可选,如果使用Docker内SSL)
|
||
volumes:
|
||
- ./frontend:/usr/share/nginx/html
|
||
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
|
||
- ./certbot/conf:/etc/letsencrypt # 可选
|
||
- ./certbot/www:/var/www/certbot # 可选
|
||
depends_on:
|
||
- backend
|
||
networks:
|
||
- wanwanyun-network
|
||
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
|
||
|
||
certbot: # 可选:Docker内自动续期SSL证书
|
||
image: certbot/certbot
|
||
container_name: wanwanyun-certbot
|
||
restart: unless-stopped
|
||
volumes:
|
||
- ./certbot/conf:/etc/letsencrypt
|
||
- ./certbot/www:/var/www/certbot
|
||
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
|
||
|
||
networks:
|
||
wanwanyun-network:
|
||
driver: bridge
|
||
```
|
||
|
||
### 2. Nginx配置(Docker内部)
|
||
|
||
文件位置: `nginx/nginx.conf`
|
||
|
||
```nginx
|
||
server {
|
||
listen 80;
|
||
server_name localhost;
|
||
|
||
# 前端静态文件
|
||
location / {
|
||
root /usr/share/nginx/html;
|
||
index index.html;
|
||
try_files $uri $uri/ =404;
|
||
}
|
||
|
||
# 后端API反向代理
|
||
location /api/ {
|
||
proxy_pass http://backend:40001;
|
||
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;
|
||
}
|
||
|
||
# 分享链接重定向
|
||
location /s/ {
|
||
proxy_pass http://backend:40001;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3. 环境变量配置(可选)
|
||
|
||
创建 `.env` 文件:
|
||
```env
|
||
# 数据库配置
|
||
DB_PATH=/app/users.db
|
||
|
||
# JWT密钥(请修改为随机字符串)
|
||
JWT_SECRET=your-secret-key-change-this-in-production
|
||
|
||
# 后端端口
|
||
PORT=40001
|
||
|
||
# 最大上传大小(字节)
|
||
MAX_UPLOAD_SIZE=104857600
|
||
|
||
# 生产环境标志
|
||
NODE_ENV=production
|
||
```
|
||
|
||
### 4. 目录结构说明
|
||
|
||
```
|
||
/var/www/wanwanyun/
|
||
├── backend/ # 后端代码
|
||
│ ├── server.js # 主服务器文件
|
||
│ ├── package.json # Node.js依赖
|
||
│ ├── Dockerfile # 后端镜像构建文件
|
||
│ └── users.db # SQLite数据库(自动生成)
|
||
│
|
||
├── frontend/ # 前端代码
|
||
│ ├── index.html # 登录页面
|
||
│ ├── app.html # 主应用页面
|
||
│ ├── app.js # Vue.js应用逻辑
|
||
│ └── libs/ # 第三方库
|
||
│ ├── vue.global.js
|
||
│ ├── axios.min.js
|
||
│ └── fontawesome/
|
||
│
|
||
├── nginx/ # Nginx配置
|
||
│ ├── nginx.conf # 当前使用的配置
|
||
│ └── nginx.conf.example # 配置示例
|
||
│
|
||
├── upload-tool/ # 上传工具
|
||
│ └── dist/
|
||
│ └── 玩玩云上传工具.exe
|
||
│
|
||
├── certbot/ # SSL证书(可选)
|
||
│ ├── conf/
|
||
│ └── www/
|
||
│
|
||
└── docker-compose.yml # Docker编排文件
|
||
```
|
||
|
||
---
|
||
|
||
## 常见问题解决
|
||
|
||
### 问题1: 502 Bad Gateway
|
||
|
||
**症状**: 访问网站显示nginx 502错误
|
||
|
||
**原因**:
|
||
- Docker容器未启动
|
||
- 宝塔nginx配置错误(HTTPS代理到HTTP容器)
|
||
- 端口冲突
|
||
|
||
**解决方案**:
|
||
|
||
```bash
|
||
# 1. 检查容器状态
|
||
docker-compose ps
|
||
|
||
# 2. 查看容器日志
|
||
docker-compose logs backend
|
||
docker-compose logs frontend
|
||
|
||
# 3. 重启容器
|
||
docker-compose restart
|
||
|
||
# 4. 检查宝塔nginx配置
|
||
# 确保proxy_pass使用HTTP而不是HTTPS
|
||
proxy_pass http://127.0.0.1:8080; # 正确
|
||
# proxy_pass https://127.0.0.1:8443; # 错误(如果Docker内未配置SSL)
|
||
|
||
# 5. 检查端口占用
|
||
netstat -tulnp | grep 8080
|
||
netstat -tulnp | grep 40001
|
||
```
|
||
|
||
### 问题2: 上传工具无法下载
|
||
|
||
**症状**: 点击"下载上传工具"后浏览器报错
|
||
|
||
**原因**: Docker容器未挂载 `upload-tool` 目录
|
||
|
||
**解决方案**:
|
||
|
||
```bash
|
||
# 1. 检查docker-compose.yml中是否有以下配置
|
||
# backend服务的volumes部分应包含:
|
||
- ./upload-tool:/upload-tool
|
||
|
||
# 2. 检查文件是否存在
|
||
ls -la /var/www/wanwanyun/upload-tool/dist/
|
||
|
||
# 3. 重新创建容器(不是重启)
|
||
cd /var/www/wanwanyun
|
||
docker-compose up -d --force-recreate backend
|
||
|
||
# 4. 验证容器内可访问文件
|
||
docker exec wanwanyun-backend ls -la /upload-tool/dist/
|
||
```
|
||
|
||
### 问题3: SFTP连接失败
|
||
|
||
**症状**: 保存SFTP配置时报错 "Connection refused" 或 "Permission denied"
|
||
|
||
**原因**:
|
||
- SFTP服务器IP/端口错误
|
||
- 防火墙阻止
|
||
- 认证信息错误
|
||
- 服务器IP被SFTP服务器限制
|
||
|
||
**解决方案**:
|
||
|
||
```bash
|
||
# 1. 在服务器上测试SFTP连接
|
||
sshpass -p 'YOUR_PASSWORD' sftp -P 22 username@sftp.server.com
|
||
|
||
# 2. 检查防火墙
|
||
# 确保后端容器可以访问外部SFTP服务器
|
||
docker exec wanwanyun-backend ping sftp.server.com
|
||
|
||
# 3. 如果SFTP服务器限制IP
|
||
# 需要在SFTP服务器上添加Docker服务器IP到白名单
|
||
|
||
# 4. 检查后端日志
|
||
docker logs wanwanyun-backend | grep -i sftp
|
||
```
|
||
|
||
### 问题4: 文件删除失败 "Permission denied"
|
||
|
||
**症状**: 删除某些文件时提示权限被拒绝
|
||
|
||
**原因**: SFTP chroot安全限制,根目录文件不可删除
|
||
|
||
**解决方案**:
|
||
|
||
这**不是bug**,是安全设计:
|
||
- `/` 根目录: 只读,系统配置文件(.bashrc等)
|
||
- `/files` 目录: 可读写,用户工作目录
|
||
|
||
**建议**: 所有文件应上传到 `/files` 目录
|
||
|
||
### 问题5: 语法错误 "Uncaught SyntaxError"
|
||
|
||
**症状**: 浏览器控制台显示 app.js 语法错误
|
||
|
||
**原因**: JavaScript字符串中有字面换行符
|
||
|
||
**解决方案**:
|
||
|
||
```bash
|
||
# 检查是否有换行符错误
|
||
cd /var/www/wanwanyun/frontend
|
||
cat -A app.js | grep -n "\\$"
|
||
|
||
# 如果发现问题,重新从本地同步
|
||
scp C:/Users/Administrator/Desktop/ftp-web-manager/frontend/app.js root@SERVER:/var/www/wanwanyun/frontend/
|
||
|
||
# 重启前端容器
|
||
docker-compose restart frontend
|
||
```
|
||
|
||
### 问题6: 数据库锁定 "Database is locked"
|
||
|
||
**症状**: 多个用户同时操作时报数据库锁定错误
|
||
|
||
**原因**: SQLite不支持高并发写入
|
||
|
||
**解决方案**:
|
||
|
||
1. **短期方案**: 增加超时时间
|
||
|
||
修改 `backend/server.js`:
|
||
```javascript
|
||
const db = new Database('users.db', {
|
||
timeout: 10000 // 增加到10秒
|
||
});
|
||
```
|
||
|
||
2. **长期方案**: 迁移到PostgreSQL或MySQL
|
||
|
||
### 问题7: 端口冲突
|
||
|
||
**症状**: 启动容器时报错 "port is already allocated"
|
||
|
||
**解决方案**:
|
||
|
||
```bash
|
||
# 1. 查找占用端口的进程
|
||
netstat -tulnp | grep 8080
|
||
netstat -tulnp | grep 40001
|
||
|
||
# 2. 停止冲突的服务
|
||
systemctl stop nginx # 如果是系统nginx占用8080
|
||
|
||
# 3. 或修改docker-compose.yml中的端口映射
|
||
# 将 "8080:80" 改为 "8081:80"
|
||
# 相应修改宝塔nginx配置中的proxy_pass端口
|
||
```
|
||
|
||
### 问题8: SSL证书过期
|
||
|
||
**症状**: 浏览器显示证书无效警告
|
||
|
||
**解决方案**:
|
||
|
||
#### 使用宝塔面板:
|
||
```bash
|
||
# 在宝塔面板网站设置中点击"续签证书"
|
||
# 或使用宝塔计划任务自动续签
|
||
```
|
||
|
||
#### 使用Certbot (Docker):
|
||
```bash
|
||
# 手动续签
|
||
docker-compose run --rm certbot renew
|
||
|
||
# 重载nginx
|
||
docker-compose exec frontend nginx -s reload
|
||
|
||
# certbot容器会自动每12小时检查并续签
|
||
```
|
||
|
||
### 问题9: 容器内存不足
|
||
|
||
**症状**: 容器频繁重启,日志显示 "Out of memory"
|
||
|
||
**解决方案**:
|
||
|
||
```bash
|
||
# 1. 检查内存使用
|
||
docker stats
|
||
|
||
# 2. 限制容器内存(在docker-compose.yml中)
|
||
services:
|
||
backend:
|
||
# ... 其他配置
|
||
deploy:
|
||
resources:
|
||
limits:
|
||
memory: 512M
|
||
reservations:
|
||
memory: 256M
|
||
|
||
# 3. 清理Docker缓存
|
||
docker system prune -a
|
||
```
|
||
|
||
### 问题10: X-Forwarded-Proto检测失败
|
||
|
||
**症状**: 下载上传工具时生成的URL是HTTP而不是HTTPS
|
||
|
||
**原因**: 反向代理未传递协议头
|
||
|
||
**解决方案**:
|
||
|
||
确保宝塔nginx配置包含:
|
||
```nginx
|
||
proxy_set_header X-Forwarded-Proto $scheme;
|
||
```
|
||
|
||
验证后端正确读取:
|
||
```javascript
|
||
// backend/server.js
|
||
const protocol = req.get('x-forwarded-proto') || req.protocol;
|
||
```
|
||
|
||
---
|
||
|
||
## 维护操作
|
||
|
||
### 日常维护
|
||
|
||
#### 查看日志
|
||
```bash
|
||
# 查看所有容器日志
|
||
docker-compose logs -f
|
||
|
||
# 查看特定容器日志
|
||
docker-compose logs -f backend
|
||
docker-compose logs -f frontend
|
||
|
||
# 查看最近100行
|
||
docker-compose logs --tail=100 backend
|
||
|
||
# 实时滚动日志
|
||
docker-compose logs -f --tail=50
|
||
```
|
||
|
||
#### 重启服务
|
||
```bash
|
||
# 重启所有容器
|
||
docker-compose restart
|
||
|
||
# 重启特定容器
|
||
docker-compose restart backend
|
||
docker-compose restart frontend
|
||
|
||
# 重新创建容器(配置更改后)
|
||
docker-compose up -d --force-recreate
|
||
```
|
||
|
||
#### 停止和启动
|
||
```bash
|
||
# 停止所有容器
|
||
docker-compose stop
|
||
|
||
# 启动所有容器
|
||
docker-compose start
|
||
|
||
# 完全停止并移除容器
|
||
docker-compose down
|
||
|
||
# 启动(创建容器)
|
||
docker-compose up -d
|
||
```
|
||
|
||
### 更新部署
|
||
|
||
#### 更新代码
|
||
```bash
|
||
# 1. 备份数据库
|
||
cp /var/www/wanwanyun/backend/users.db /var/www/wanwanyun/backend/users.db.backup
|
||
|
||
# 2. 拉取最新代码(如果使用Git)
|
||
cd /var/www/wanwanyun
|
||
git pull
|
||
|
||
# 3. 或从本地上传更新的文件
|
||
scp C:/Users/Administrator/Desktop/ftp-web-manager/backend/server.js root@SERVER:/var/www/wanwanyun/backend/
|
||
scp C:/Users/Administrator/Desktop/ftp-web-manager/frontend/app.js root@SERVER:/var/www/wanwanyun/frontend/
|
||
|
||
# 4. 重启容器
|
||
docker-compose restart backend frontend
|
||
```
|
||
|
||
#### 更新Docker镜像
|
||
```bash
|
||
# 1. 停止容器
|
||
docker-compose down
|
||
|
||
# 2. 重新构建后端镜像
|
||
docker build -t wanwanyun-backend -f backend/Dockerfile .
|
||
|
||
# 3. 拉取最新官方镜像
|
||
docker-compose pull frontend certbot
|
||
|
||
# 4. 启动
|
||
docker-compose up -d
|
||
```
|
||
|
||
### 备份和恢复
|
||
|
||
#### 备份数据
|
||
```bash
|
||
# 创建备份目录
|
||
mkdir -p /backup/wanwanyun/$(date +%Y%m%d)
|
||
|
||
# 备份数据库
|
||
cp /var/www/wanwanyun/backend/users.db /backup/wanwanyun/$(date +%Y%m%d)/
|
||
|
||
# 备份整个项目
|
||
tar -czf /backup/wanwanyun/$(date +%Y%m%d)/wanwanyun-full.tar.gz /var/www/wanwanyun
|
||
|
||
# 定期备份脚本(添加到crontab)
|
||
# 每天凌晨2点备份
|
||
# 0 2 * * * /usr/bin/tar -czf /backup/wanwanyun/$(date +\%Y\%m\%d)/backup.tar.gz /var/www/wanwanyun/backend/users.db
|
||
```
|
||
|
||
#### 恢复数据
|
||
```bash
|
||
# 停止容器
|
||
docker-compose down
|
||
|
||
# 恢复数据库
|
||
cp /backup/wanwanyun/20251108/users.db /var/www/wanwanyun/backend/
|
||
|
||
# 启动容器
|
||
docker-compose up -d
|
||
```
|
||
|
||
### 监控和性能
|
||
|
||
#### 监控容器资源
|
||
```bash
|
||
# 实时监控
|
||
docker stats
|
||
|
||
# 查看容器详细信息
|
||
docker inspect wanwanyun-backend
|
||
docker inspect wanwanyun-frontend
|
||
```
|
||
|
||
#### 性能优化
|
||
|
||
1. **启用Gzip压缩** (nginx/nginx.conf):
|
||
```nginx
|
||
gzip on;
|
||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
|
||
gzip_min_length 1000;
|
||
```
|
||
|
||
2. **配置浏览器缓存**:
|
||
```nginx
|
||
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
|
||
expires 7d;
|
||
add_header Cache-Control "public, immutable";
|
||
}
|
||
```
|
||
|
||
3. **限制并发连接**:
|
||
```nginx
|
||
limit_conn_zone $binary_remote_addr zone=addr:10m;
|
||
limit_conn addr 10;
|
||
```
|
||
|
||
### 清理和优化
|
||
|
||
```bash
|
||
# 清理未使用的Docker资源
|
||
docker system prune -a
|
||
|
||
# 清理日志(如果过大)
|
||
truncate -s 0 /var/lib/docker/containers/*/*-json.log
|
||
|
||
# 查看磁盘使用
|
||
docker system df
|
||
```
|
||
|
||
---
|
||
|
||
## 安全建议
|
||
|
||
### 1. 修改默认配置
|
||
|
||
- 修改JWT_SECRET为随机字符串
|
||
- 修改数据库默认路径
|
||
- 限制管理员账号数量
|
||
|
||
### 2. 防火墙配置
|
||
|
||
```bash
|
||
# 只开放必要端口
|
||
ufw allow 80/tcp
|
||
ufw allow 443/tcp
|
||
ufw deny 40001/tcp # 不对外开放后端端口
|
||
ufw deny 8080/tcp # 不对外开放Docker HTTP端口
|
||
ufw enable
|
||
```
|
||
|
||
### 3. 日志审计
|
||
|
||
```bash
|
||
# 定期检查访问日志
|
||
tail -f /www/wwwlogs/example.com.log
|
||
|
||
# 查找异常请求
|
||
grep "POST /api/login" /www/wwwlogs/example.com.log | grep -v "200"
|
||
```
|
||
|
||
### 4. 定期更新
|
||
|
||
```bash
|
||
# 更新系统
|
||
apt update && apt upgrade -y
|
||
|
||
# 更新Docker镜像
|
||
docker-compose pull
|
||
docker-compose up -d
|
||
```
|
||
|
||
---
|
||
|
||
## 故障排查流程
|
||
|
||
### 基本诊断命令
|
||
|
||
```bash
|
||
# 1. 检查容器状态
|
||
docker-compose ps
|
||
|
||
# 2. 检查端口监听
|
||
netstat -tulnp | grep -E "80|443|8080|40001"
|
||
|
||
# 3. 测试后端API
|
||
curl http://localhost:40001/api/user/profile
|
||
|
||
# 4. 测试前端访问
|
||
curl http://localhost:8080
|
||
|
||
# 5. 检查nginx配置
|
||
nginx -t
|
||
|
||
# 6. 查看完整日志
|
||
docker-compose logs --tail=100
|
||
|
||
# 7. 进入容器调试
|
||
docker exec -it wanwanyun-backend sh
|
||
docker exec -it wanwanyun-frontend sh
|
||
```
|
||
|
||
### 故障决策树
|
||
|
||
```
|
||
网站无法访问
|
||
├── 502 错误
|
||
│ ├── 容器未启动 → docker-compose up -d
|
||
│ ├── nginx配置错误 → 检查proxy_pass
|
||
│ └── 端口冲突 → netstat检查
|
||
│
|
||
├── 404 错误
|
||
│ ├── 路由配置错误 → 检查nginx.conf
|
||
│ └── 文件不存在 → 检查/usr/share/nginx/html
|
||
│
|
||
├── 500 错误
|
||
│ ├── 后端崩溃 → docker logs backend
|
||
│ ├── 数据库错误 → 检查users.db权限
|
||
│ └── 代码错误 → 查看error.log
|
||
│
|
||
└── 连接超时
|
||
├── 防火墙阻止 → ufw status
|
||
├── 容器网络问题 → docker network ls
|
||
└── DNS解析失败 → ping域名
|
||
```
|
||
|
||
---
|
||
|
||
## 联系和支持
|
||
|
||
如果遇到无法解决的问题:
|
||
|
||
1. 收集以下信息:
|
||
- 错误信息截图
|
||
- `docker-compose logs` 输出
|
||
- `nginx -T` 配置输出
|
||
- 系统信息 `uname -a`
|
||
|
||
2. 检查日志中的错误堆栈
|
||
|
||
3. 参考本指南的"常见问题解决"部分
|
||
|
||
---
|
||
|
||
## 附录
|
||
|
||
### A. 完整的docker-compose.yml示例
|
||
|
||
参见项目根目录的 `docker-compose.yml` 文件
|
||
|
||
### B. 完整的Nginx配置示例
|
||
|
||
参见 `nginx/nginx.conf` 和 `nginx/nginx.conf.example`
|
||
|
||
### C. 后端Dockerfile示例
|
||
|
||
```dockerfile
|
||
FROM node:18-alpine
|
||
|
||
WORKDIR /app
|
||
|
||
COPY backend/package*.json ./
|
||
RUN npm install --production
|
||
|
||
COPY backend/ ./
|
||
|
||
EXPOSE 40001
|
||
|
||
CMD ["node", "server.js"]
|
||
```
|
||
|
||
### D. 环境检查脚本
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
# 保存为 check-env.sh
|
||
|
||
echo "=== 玩玩云环境检查 ==="
|
||
|
||
echo -e "\n1. Docker版本:"
|
||
docker --version
|
||
|
||
echo -e "\n2. Docker Compose版本:"
|
||
docker-compose --version
|
||
|
||
echo -e "\n3. 容器状态:"
|
||
docker-compose ps
|
||
|
||
echo -e "\n4. 端口监听:"
|
||
netstat -tulnp | grep -E "80|443|8080|40001"
|
||
|
||
echo -e "\n5. 磁盘空间:"
|
||
df -h /var/www/wanwanyun
|
||
|
||
echo -e "\n6. 内存使用:"
|
||
docker stats --no-stream
|
||
|
||
echo -e "\n7. 最近错误日志:"
|
||
docker-compose logs --tail=20 | grep -i error
|
||
|
||
echo -e "\n=== 检查完成 ==="
|
||
```
|
||
|
||
---
|
||
|
||
**文档版本**: v1.0
|
||
**最后更新**: 2025-11-08
|
||
**适用版本**: 玩玩云 v1.0
|
||
|
||
---
|
||
|
||
## SFTP服务器配置指南
|
||
|
||
### 方案:使用bindfs实现根目录可写的chroot
|
||
|
||
本项目推荐使用bindfs技术配置SFTP服务器,可以实现:
|
||
- ✅ **根目录可写** - 上传工具可直接上传到 `/filename`
|
||
- ✅ **Chroot隔离** - 用户只能访问独立空间,安全性高
|
||
- ✅ **无需修改代码** - 上传工具保持原样
|
||
|
||
### 配置步骤
|
||
|
||
#### 1. 安装必要工具
|
||
|
||
```bash
|
||
# 在SFTP服务器上执行
|
||
apt-get update
|
||
apt-get install -y bindfs openssh-server
|
||
```
|
||
|
||
#### 2. 创建用户和目录
|
||
|
||
```bash
|
||
# 创建真实数据目录
|
||
mkdir -p /var/sftp_data/wwy_upload
|
||
chown -R wwy_upload:wwy_upload /var/sftp_data/wwy_upload
|
||
chmod 755 /var/sftp_data/wwy_upload
|
||
|
||
# 创建chroot目录
|
||
mkdir -p /home/wwy_ftp_upload
|
||
|
||
# 创建用户
|
||
useradd -d /var/sftp_data/wwy_upload -s /bin/bash wwy_upload
|
||
printf 'wwy_upload:Wwy@2024Pass' | chpasswd
|
||
```
|
||
|
||
#### 3. 配置bindfs挂载
|
||
|
||
```bash
|
||
# 使用bindfs挂载(关键步骤)
|
||
bindfs --mirror=wwy_upload \
|
||
--force-user=root --force-group=root \
|
||
--perms=0755 \
|
||
/var/sftp_data/wwy_upload /home/wwy_ftp_upload
|
||
```
|
||
|
||
**参数说明**:
|
||
- `--mirror=wwy_upload`: 以wwy_upload用户身份镜像所有操作
|
||
- `--force-user=root --force-group=root`: 让目录看起来归root所有(满足chroot要求)
|
||
- `--perms=0755`: 设置目录权限
|
||
|
||
#### 4. 配置开机自动挂载
|
||
|
||
编辑 `/etc/fstab`,添加:
|
||
|
||
```
|
||
/var/sftp_data/wwy_upload /home/wwy_ftp_upload fuse.bindfs mirror=wwy_upload,force-user=root,force-group=root,perms=0755 0 0
|
||
```
|
||
|
||
#### 5. 配置SSH chroot
|
||
|
||
编辑 `/etc/ssh/sshd_config`,添加:
|
||
|
||
```
|
||
Match User wwy_upload
|
||
ChrootDirectory /home/wwy_ftp_upload
|
||
ForceCommand internal-sftp
|
||
AllowTcpForwarding no
|
||
X11Forwarding no
|
||
```
|
||
|
||
重启SSH服务:
|
||
|
||
```bash
|
||
systemctl restart sshd
|
||
```
|
||
|
||
#### 6. 测试配置
|
||
|
||
```bash
|
||
# 测试上传到根目录
|
||
echo 'Test file' > /tmp/test.txt
|
||
sshpass -p 'Wwy@2024Pass' sftp wwy_upload@localhost <<EOF
|
||
put /tmp/test.txt /testfile.txt
|
||
ls -l /
|
||
bye
|
||
EOF
|
||
|
||
# 查看实际文件位置
|
||
ls -lh /var/sftp_data/wwy_upload/
|
||
```
|
||
|
||
### 技术原理
|
||
|
||
**bindfs工作原理**:
|
||
1. 真实数据存储在 `/var/sftp_data/wwy_upload`(用户拥有写权限)
|
||
2. bindfs将其挂载到 `/home/wwy_ftp_upload`(显示为root所有)
|
||
3. OpenSSH chroot到 `/home/wwy_ftp_upload`(满足安全要求)
|
||
4. 用户写入被镜像到真实目录(实际文件归wwy_upload所有)
|
||
|
||
**优势**:
|
||
- 绕过了OpenSSH chroot根目录必须只读的限制
|
||
- 保持了chroot的安全隔离特性
|
||
- 上传工具无需修改,直接上传到 `/filename`
|
||
|
||
---
|
||
|
||
## 下载功能说明
|
||
|
||
### 双模式下载
|
||
|
||
系统支持两种下载模式,自动选择:
|
||
|
||
#### 模式1: HTTP直接下载(推荐,速度快)
|
||
|
||
**配置**: 在"设置"中填写"HTTP下载基础URL"
|
||
|
||
**工作方式**:
|
||
- 前端直接打开HTTP下载链接
|
||
- 浏览器从HTTP服务器直接下载
|
||
- 速度快,服务器压力小
|
||
|
||
**适用场景**:
|
||
- SFTP服务器同时提供HTTP访问
|
||
- 有独立的文件CDN服务
|
||
|
||
#### 模式2: SFTP流式下载(默认,无需配置)
|
||
|
||
**配置**: 无需配置HTTP URL
|
||
|
||
**工作方式**:
|
||
1. 前端请求后端API `/api/files/download`
|
||
2. 后端通过SFTP连接文件服务器
|
||
3. 先获取文件大小(`sftp.stat()`)
|
||
4. 设置响应头 `Content-Length`
|
||
5. 创建文件流(`sftp.createReadStream()`)
|
||
6. 流式传输到浏览器(`stream.pipe(res)`)
|
||
|
||
**特点**:
|
||
- ✅ 服务器零存储(不保存临时文件)
|
||
- ✅ 内存占用低(流式传输)
|
||
- ✅ 显示完整下载进度(文件大小、速度、剩余时间)
|
||
- ✅ 无需配置(开箱即用)
|
||
|
||
**代码实现** (`backend/server.js`):
|
||
|
||
```javascript
|
||
app.get('/api/files/download', authMiddleware, async (req, res) => {
|
||
const filePath = req.query.path;
|
||
const sftp = await connectToSFTP(req.user);
|
||
|
||
// 获取文件大小(用于显示下载进度)
|
||
const fileStats = await sftp.stat(filePath);
|
||
const fileSize = fileStats.size;
|
||
|
||
// 设置响应头
|
||
res.setHeader('Content-Type', 'application/octet-stream');
|
||
res.setHeader('Content-Length', fileSize); // 浏览器可显示进度
|
||
res.setHeader('Content-Disposition', 'attachment; filename="..."');
|
||
|
||
// 流式传输(服务器不保存临时文件)
|
||
const stream = sftp.createReadStream(filePath);
|
||
stream.pipe(res);
|
||
});
|
||
```
|
||
|
||
### 自动选择逻辑
|
||
|
||
前端自动判断使用哪种模式:
|
||
|
||
```javascript
|
||
downloadFile(file) {
|
||
if (file.httpDownloadUrl) {
|
||
// 如果配置了HTTP URL,使用HTTP直接下载
|
||
window.open(file.httpDownloadUrl, "_blank");
|
||
} else {
|
||
// 如果没有配置,通过后端SFTP下载
|
||
const link = document.createElement('a');
|
||
link.href = `${this.apiBase}/api/files/download?path=${filePath}&token=${token}`;
|
||
link.click();
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 版本更新日志
|
||
|
||
### v1.1 (2025-11-09)
|
||
|
||
**新增功能**:
|
||
- ✅ SFTP流式下载(无需配置HTTP URL)
|
||
- ✅ 下载进度显示(文件大小、速度、剩余时间)
|
||
- ✅ bindfs SFTP服务器配置方案
|
||
|
||
**改进**:
|
||
- ✅ 服务器零存储下载(纯中转)
|
||
- ✅ 下载逻辑自动选择(HTTP/SFTP)
|
||
- ✅ 优化用户体验
|
||
|
||
**修复**:
|
||
- ✅ 修复下载无进度显示的问题
|
||
- ✅ 修复未配置HTTP URL时无法下载的问题
|
||
|
||
### v1.0 (2025-11-08)
|
||
|
||
**初始版本**:
|
||
- ✅ 文件管理基础功能
|
||
- ✅ 文件分享功能
|
||
- ✅ 多用户系统
|
||
- ✅ 上传工具
|
||
- ✅ Docker部署
|
||
|
||
---
|
||
|
||
**文档版本**: v1.1
|
||
**最后更新**: 2025-11-09
|
||
**适用版本**: 玩玩云 v1.1
|