Files
vue-driven-cloud-storage/DOCKER部署指南.md
WanWanYun 0f133962dc Initial commit - 玩玩云文件管理系统 v1.0.0
- 完整的前后端代码
- 支持本地存储和SFTP存储
- 文件分享功能
- 上传工具源代码
- 完整的部署文档
- Nginx配置模板

技术栈:
- 后端: Node.js + Express + SQLite
- 前端: Vue.js 3 + Axios
- 存储: 本地存储 / SFTP远程存储
2025-11-10 21:50:16 +08:00

27 KiB
Raw Blame History

玩玩云 - 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: 准备服务器环境

# 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: 上传项目文件

# 在服务器上创建项目目录
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:

cd /var/www/wanwanyun
git clone YOUR_REPOSITORY_URL .

步骤3: 构建后端镜像

cd /var/www/wanwanyun
docker build -t wanwanyun-backend -f backend/Dockerfile .

Dockerfile内容(应该在 backend/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: 启动容器

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:

# 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;
}
  1. 重载Nginx
nginx -t  # 测试配置
nginx -s reload  # 重载配置

系统Nginx配置无宝塔

配置文件位置: /etc/nginx/sites-available/wanwanyun.conf

# 与上述配置相同但SSL证书路径可能不同
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

创建软链接并重载:

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 配置

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

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 文件:

# 数据库配置
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容器
  • 端口冲突

解决方案:

# 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 目录

解决方案:

# 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服务器限制

解决方案:

# 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字符串中有字面换行符

解决方案:

# 检查是否有换行符错误
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:

const db = new Database('users.db', {
  timeout: 10000  // 增加到10秒
});
  1. 长期方案: 迁移到PostgreSQL或MySQL

问题7: 端口冲突

症状: 启动容器时报错 "port is already allocated"

解决方案:

# 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证书过期

症状: 浏览器显示证书无效警告

解决方案:

使用宝塔面板:

# 在宝塔面板网站设置中点击"续签证书"
# 或使用宝塔计划任务自动续签

使用Certbot (Docker):

# 手动续签
docker-compose run --rm certbot renew

# 重载nginx
docker-compose exec frontend nginx -s reload

# certbot容器会自动每12小时检查并续签

问题9: 容器内存不足

症状: 容器频繁重启,日志显示 "Out of memory"

解决方案:

# 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配置包含:

proxy_set_header X-Forwarded-Proto $scheme;

验证后端正确读取:

// backend/server.js
const protocol = req.get('x-forwarded-proto') || req.protocol;

维护操作

日常维护

查看日志

# 查看所有容器日志
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

重启服务

# 重启所有容器
docker-compose restart

# 重启特定容器
docker-compose restart backend
docker-compose restart frontend

# 重新创建容器(配置更改后)
docker-compose up -d --force-recreate

停止和启动

# 停止所有容器
docker-compose stop

# 启动所有容器
docker-compose start

# 完全停止并移除容器
docker-compose down

# 启动(创建容器)
docker-compose up -d

更新部署

更新代码

# 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镜像

# 1. 停止容器
docker-compose down

# 2. 重新构建后端镜像
docker build -t wanwanyun-backend -f backend/Dockerfile .

# 3. 拉取最新官方镜像
docker-compose pull frontend certbot

# 4. 启动
docker-compose up -d

备份和恢复

备份数据

# 创建备份目录
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

恢复数据

# 停止容器
docker-compose down

# 恢复数据库
cp /backup/wanwanyun/20251108/users.db /var/www/wanwanyun/backend/

# 启动容器
docker-compose up -d

监控和性能

监控容器资源

# 实时监控
docker stats

# 查看容器详细信息
docker inspect wanwanyun-backend
docker inspect wanwanyun-frontend

性能优化

  1. 启用Gzip压缩 (nginx/nginx.conf):
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
gzip_min_length 1000;
  1. 配置浏览器缓存:
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    expires 7d;
    add_header Cache-Control "public, immutable";
}
  1. 限制并发连接:
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_conn addr 10;

清理和优化

# 清理未使用的Docker资源
docker system prune -a

# 清理日志(如果过大)
truncate -s 0 /var/lib/docker/containers/*/*-json.log

# 查看磁盘使用
docker system df

安全建议

1. 修改默认配置

  • 修改JWT_SECRET为随机字符串
  • 修改数据库默认路径
  • 限制管理员账号数量

2. 防火墙配置

# 只开放必要端口
ufw allow 80/tcp
ufw allow 443/tcp
ufw deny 40001/tcp  # 不对外开放后端端口
ufw deny 8080/tcp   # 不对外开放Docker HTTP端口
ufw enable

3. 日志审计

# 定期检查访问日志
tail -f /www/wwwlogs/example.com.log

# 查找异常请求
grep "POST /api/login" /www/wwwlogs/example.com.log | grep -v "200"

4. 定期更新

# 更新系统
apt update && apt upgrade -y

# 更新Docker镜像
docker-compose pull
docker-compose up -d

故障排查流程

基本诊断命令

# 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.confnginx/nginx.conf.example

C. 后端Dockerfile示例

FROM node:18-alpine

WORKDIR /app

COPY backend/package*.json ./
RUN npm install --production

COPY backend/ ./

EXPOSE 40001

CMD ["node", "server.js"]

D. 环境检查脚本

#!/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. 安装必要工具

# 在SFTP服务器上执行
apt-get update
apt-get install -y bindfs openssh-server

2. 创建用户和目录

# 创建真实数据目录
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挂载

# 使用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服务

systemctl restart sshd

6. 测试配置

# 测试上传到根目录
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):

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);
});

自动选择逻辑

前端自动判断使用哪种模式:

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