Completed: - Add 6 core database documents (docs/01-平台基础层/07-数据库/) Architecture overview, migration history, environment comparison, tech debt tracking, seed data management, PostgreSQL extensions - Restructure deployment docs: archive 20 legacy files to _archive-2025/ - Create unified daily operations manual (01-日常更新操作手册.md) - Add pending deployment change tracker (03-待部署变更清单.md) - Update database development standard to v3.0 (three iron rules) - Fix Prisma schema type drift: align @db.* annotations with actual DB IIT: UUID/Timestamptz(6), SSA: Timestamp(6)/VarChar(20/50/100) - Add migration: 20260227_align_schema_with_db_types (idempotent ALTER) - Add Cursor Rule for auto-reminding deployment change documentation - Update system status guide v6.4 with deployment and DB doc references - Add architecture consultation docs (Prisma guide, SAE deployment guide) Technical details: - Manual migration due to shadow DB limitation (TD-001 in tech debt) - Deployment docs reduced from 20+ scattered files to 3 core documents - Cursor Rule triggers on schema.prisma, package.json, Dockerfile changes Made-with: Cursor
1223 lines
30 KiB
Markdown
1223 lines
30 KiB
Markdown
# Dify ECS 部署完全指南
|
||
|
||
**文档版本**: v1.1 (修复致命配置错误)
|
||
**创建时间**: 2025-12-13
|
||
**最后修订**: 2025-12-13
|
||
**适用范围**: AIclinicalresearch 平台 - Dify RAG 服务部署
|
||
**目标读者**: 运维工程师、后端开发工程师
|
||
|
||
**v1.1 更新日志**:
|
||
- ✅ 修复:Redis 配置从 `localhost` 改为 `redis`(致命错误)
|
||
- ✅ 新增:Swap 分区配置步骤(避免 OOM)
|
||
- ✅ 修正:强调使用官方 docker-compose.yaml(包含 Nginx 网关)
|
||
- ✅ 完善:故障排查章节,新增 Redis 连接失败和 CORS 错误的解决方案
|
||
|
||
---
|
||
|
||
## 📋 文档目录
|
||
|
||
1. [为什么选择 ECS + Docker Compose](#为什么选择-ecs--docker-compose)
|
||
2. [部署架构图](#部署架构图)
|
||
3. [前置准备清单](#前置准备清单)
|
||
4. [ECS 服务器配置](#ecs-服务器配置)
|
||
5. [安装步骤](#安装步骤)
|
||
6. [配置说明](#配置说明)
|
||
7. [启动与验证](#启动与验证)
|
||
8. [监控与维护](#监控与维护)
|
||
9. [故障排查](#故障排查)
|
||
10. [注意事项与禁忌](#注意事项与禁忌)
|
||
|
||
---
|
||
|
||
## 为什么选择 ECS + Docker Compose
|
||
|
||
### ✅ 核心原因
|
||
|
||
#### 1. **数据合规与隐私(医疗行业红线)**
|
||
|
||
```
|
||
❌ Dify 云服务 (SaaS):数据上传到第三方服务器
|
||
✅ ECS 自建:数据 100% 在自己的阿里云账号内
|
||
```
|
||
|
||
**影响**:
|
||
- 三甲医院对科研数据出院有极严格管控
|
||
- 您可以对客户说:"数据就在我们的私有云服务器上,未来可部署在医院内网"
|
||
- 符合 PRD 中的核心要求:"数据 100% 本地"
|
||
|
||
#### 2. **商业模式适配(私有化部署能力)**
|
||
|
||
```
|
||
您的商业模式(PRD):
|
||
├─ SaaS 版(多租户)
|
||
├─ 私有化部署(医院内网)
|
||
└─ 单机版(Windows/Mac)
|
||
```
|
||
|
||
**关键**:
|
||
- Dify 云服务无法私有化交付(医院内网无法连接公有云)
|
||
- ECS + Docker Compose 可以直接打包成安装包,卖给医院做私有化部署
|
||
- 您现在的架构选型,是在为未来的商业模式铺路
|
||
|
||
#### 3. **技术迁移成本(避开"以后再切回来"的陷阱)**
|
||
|
||
```
|
||
RAG 系统迁移的复杂度:
|
||
1. 文档被切片 (Chunking)
|
||
2. 切片被向量化 (Embedding)
|
||
3. 存入向量数据库 (Weaviate/Qdrant)
|
||
4. Dify 云服务的向量数据很难无损导出
|
||
```
|
||
|
||
**后果**:3 个月后想切回自建,可能面临所有知识库需要重新上传、重新解析、重新嵌入
|
||
|
||
#### 4. **网络性能与成本**
|
||
|
||
| 路径对比 | Dify 云服务 | ECS 自建 |
|
||
|---------|-----------|---------|
|
||
| 网络路径 | SAE → 公网 → Dify → 公网 → SAE | SAE → 阿里云内网(VPC) → ECS |
|
||
| 延时 | 100-300ms | 1-5ms |
|
||
| 流量成本 | 消耗公网带宽 | 内网免费 |
|
||
| 大文件处理 | 慢且不稳定 | 毫秒级响应 |
|
||
|
||
**影响场景**:
|
||
- PKB 模块的批量文档上传
|
||
- ASL 模块的深度阅读 (Deep Read)
|
||
- 大量文档的向量化处理
|
||
|
||
---
|
||
|
||
## 部署架构图
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ 阿里云 VPC (同一区域) │
|
||
│ │
|
||
│ ┌─────────────┐ ┌─────────────────────────────┐ │
|
||
│ │ SAE (后端) │ ←内网→ │ ECS (Dify 服务) │ │
|
||
│ │ │ │ │ │
|
||
│ │ Node.js │ │ ┌─────────────────────┐ │ │
|
||
│ │ Backend │ │ │ Docker Compose: │ │ │
|
||
│ │ │ │ │ - Dify API │ │ │
|
||
│ │ │ │ │ - Weaviate (向量DB) │ │ │
|
||
│ │ │ │ │ - Nginx (反向代理) │ │ │
|
||
│ │ │ │ └─────────────────────┘ │ │
|
||
│ └─────────────┘ └─────────────────────────────┘ │
|
||
│ │ │
|
||
│ └──────────────→ RDS PostgreSQL 15 │
|
||
│ (共享数据库) │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**关键点**:
|
||
- SAE 和 ECS 必须在同一个 VPC(内网通信)
|
||
- Dify 的 PostgreSQL 数据库可以和后端共用同一个 RDS 实例(不同 Schema)
|
||
- 向量数据库 Weaviate 运行在 ECS 的 Docker 中
|
||
|
||
---
|
||
|
||
## 前置准备清单
|
||
|
||
### ✅ 必需资源
|
||
|
||
| 资源类型 | 配置建议 | 预估费用 | 用途 |
|
||
|---------|---------|---------|-----|
|
||
| **ECS 服务器** | 2核4G / 系统盘40GB / 数据盘100GB | ~200元/月 | 运行 Dify + Weaviate |
|
||
| **RDS PostgreSQL** | 已有(共用) | 0元(增量) | Dify 元数据存储 |
|
||
| **OSS 存储** | 已有(共用) | 按量计费 | 文档存储 |
|
||
| **VPC 网络** | 已有(SAE所在VPC) | 0元 | 内网通信 |
|
||
|
||
### ✅ 软件准备
|
||
|
||
```bash
|
||
# 本地开发机器需要安装(用于推送镜像)
|
||
- Docker Desktop
|
||
- 阿里云 CLI(可选)
|
||
|
||
# ECS 服务器需要安装(远程执行)
|
||
- Docker Engine
|
||
- Docker Compose
|
||
```
|
||
|
||
### ✅ 账号与权限
|
||
|
||
- 阿里云账号(已有)
|
||
- ECS 登录凭证(SSH密钥对)
|
||
- Docker 镜像仓库(阿里云容器镜像服务 ACR)
|
||
|
||
---
|
||
|
||
## ECS 服务器配置
|
||
|
||
### 步骤 1:购买 ECS 实例
|
||
|
||
1. **登录阿里云控制台** → **云服务器 ECS** → **创建实例**
|
||
|
||
2. **基础配置**:
|
||
```
|
||
地域和可用区: 与 SAE 相同(如:华东1-杭州)
|
||
实例规格: ecs.t6-c1m2.large (2核4G)
|
||
镜像: Ubuntu 22.04 LTS 64位
|
||
存储:
|
||
- 系统盘: ESSD云盘 40GB
|
||
- 数据盘: ESSD云盘 100GB (挂载到 /data)
|
||
```
|
||
|
||
3. **网络配置**:
|
||
```
|
||
专有网络 VPC: 选择 SAE 所在的 VPC
|
||
安全组: 创建新安全组,配置入方向规则(⚠️ 安全红线):
|
||
✅ 允许 22/TCP 来源:您的办公室公网IP # SSH管理
|
||
✅ 允许 80/TCP 来源:172.17.0.0/16 # Nginx(VPC内网访问)
|
||
❌ 拒绝 5000/TCP 来源:0.0.0.0/0 # Dify API禁止公网访问
|
||
❌ 拒绝 6379/TCP 来源:0.0.0.0/0 # Redis禁止公网访问
|
||
❌ 拒绝 8080/TCP 来源:0.0.0.0/0 # Weaviate禁止公网访问
|
||
✅ 拒绝 所有 来源:0.0.0.0/0 # 默认拒绝
|
||
公网IP: 分配公网IPv4地址(用于SSH登录和镜像下载)
|
||
|
||
⚠️ 安全警告:
|
||
- Dify API (5000)、Redis (6379)、Weaviate (8080) 绝对不能对公网开放
|
||
- 只允许VPC内网访问(172.17.0.0/16)
|
||
- 端口绑定到 127.0.0.1(见docker-compose.yaml配置)
|
||
```
|
||
|
||
4. **系统配置**:
|
||
```
|
||
登录凭证: 使用密钥对(推荐)或密码
|
||
实例名称: dify-ecs-prod
|
||
```
|
||
|
||
### 步骤 2:连接到 ECS
|
||
|
||
```bash
|
||
# Windows 用户使用 PowerShell 或 Git Bash
|
||
ssh -i "your-key.pem" root@<ECS公网IP>
|
||
|
||
# 首次登录后,更新系统
|
||
apt update && apt upgrade -y
|
||
```
|
||
|
||
### 步骤 3:挂载数据盘
|
||
|
||
```bash
|
||
# 查看磁盘
|
||
lsblk
|
||
|
||
# 格式化数据盘(假设为 /dev/vdb)
|
||
mkfs.ext4 /dev/vdb
|
||
|
||
# 创建挂载点
|
||
mkdir -p /data
|
||
|
||
# 挂载
|
||
mount /dev/vdb /data
|
||
|
||
# 设置开机自动挂载
|
||
echo '/dev/vdb /data ext4 defaults 0 0' >> /etc/fstab
|
||
|
||
# 验证
|
||
df -h
|
||
```
|
||
|
||
### 步骤 4:配置 Swap 分区(关键!避免 OOM)
|
||
|
||
**为什么必须配置 Swap?**
|
||
- 您的 ECS 是 2核4G 内存
|
||
- Dify 全家桶(API+Worker+Web+Redis+Weaviate+Nginx)空载就需要 3GB+
|
||
- 有人上传大文件或进行向量检索时,极易发生 OOM(内存溢出)崩溃
|
||
- Swap 是内存的"救生圈",关键时刻能保证服务不崩溃
|
||
|
||
```bash
|
||
# 创建 4GB Swap 分区
|
||
fallocate -l 4G /swapfile
|
||
|
||
# 设置权限(必须是 600,否则不安全)
|
||
chmod 600 /swapfile
|
||
|
||
# 格式化为 Swap
|
||
mkswap /swapfile
|
||
|
||
# 启用 Swap
|
||
swapon /swapfile
|
||
|
||
# 设置开机自动挂载
|
||
echo '/swapfile none swap sw 0 0' >> /etc/fstab
|
||
|
||
# 验证 Swap 已启用
|
||
free -h
|
||
# 应该看到 Swap 一行显示 4GB
|
||
|
||
# 优化 Swap 使用策略(可选)
|
||
# swappiness=10 表示尽量使用物理内存,只在必要时用 Swap
|
||
echo 'vm.swappiness=10' >> /etc/sysctl.conf
|
||
sysctl -p
|
||
```
|
||
|
||
### 步骤 5:安装 Docker
|
||
|
||
```bash
|
||
# 1. 卸载旧版本(如果有)
|
||
apt remove docker docker-engine docker.io containerd runc
|
||
|
||
# 2. 安装依赖
|
||
apt install -y ca-certificates curl gnupg lsb-release
|
||
|
||
# 3. 添加 Docker 官方 GPG key
|
||
mkdir -p /etc/apt/keyrings
|
||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||
|
||
# 4. 设置 Docker 仓库
|
||
echo \
|
||
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
|
||
$(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||
|
||
# 5. 安装 Docker Engine
|
||
apt update
|
||
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||
|
||
# 6. 启动 Docker
|
||
systemctl start docker
|
||
systemctl enable docker
|
||
|
||
# 7. 验证安装
|
||
docker --version
|
||
docker compose version
|
||
```
|
||
|
||
### 步骤 6:配置 Docker 镜像加速(可选但推荐)
|
||
|
||
```bash
|
||
# 阿里云镜像加速器(登录阿里云控制台获取专属地址)
|
||
mkdir -p /etc/docker
|
||
cat > /etc/docker/daemon.json <<EOF
|
||
{
|
||
"registry-mirrors": ["https://<your-id>.mirror.aliyuncs.com"]
|
||
}
|
||
EOF
|
||
|
||
systemctl daemon-reload
|
||
systemctl restart docker
|
||
```
|
||
|
||
---
|
||
|
||
## 安装步骤
|
||
|
||
### 步骤 1:准备 Dify 部署目录
|
||
|
||
```bash
|
||
# 在 ECS 上创建目录
|
||
mkdir -p /data/dify
|
||
cd /data/dify
|
||
|
||
# 克隆 Dify 官方仓库(使用稳定版本)
|
||
git clone https://github.com/langgenius/dify.git
|
||
cd dify
|
||
|
||
# 切换到稳定版本(建议使用最新的 release 版本)
|
||
git checkout tags/0.11.2 # 替换为最新稳定版本
|
||
|
||
# 进入 docker 目录
|
||
cd docker
|
||
|
||
# ⚠️ 重要:使用官方的 docker-compose.yaml
|
||
# 不要自己手写或大幅删减!官方配置包含了完整的服务(含 Nginx 网关)
|
||
```
|
||
|
||
### 步骤 2:配置环境变量
|
||
|
||
```bash
|
||
# 复制配置模板
|
||
cp .env.example .env
|
||
|
||
# 编辑配置文件
|
||
nano .env
|
||
```
|
||
|
||
**关键配置项**(必须修改):
|
||
|
||
```bash
|
||
# ========= 核心配置 =========
|
||
# 安装模式:self-hosted(自建)
|
||
INSTALL_MODE=self-hosted
|
||
|
||
# 密钥(必须修改,使用强密码)
|
||
SECRET_KEY=<生成一个随机字符串,至少32位>
|
||
# 生成方法:openssl rand -base64 32
|
||
|
||
# ========= 数据库配置 =========
|
||
# 使用阿里云 RDS PostgreSQL
|
||
DB_TYPE=postgres
|
||
DB_HOST=<RDS内网地址,如:rm-xxxx.pg.rds.aliyuncs.com>
|
||
DB_PORT=5432
|
||
DB_NAME=dify_prod
|
||
DB_USERNAME=dify_user
|
||
DB_PASSWORD=<your-password>
|
||
|
||
# 注意:需要在 RDS 中创建单独的数据库和用户
|
||
# 执行:CREATE DATABASE dify_prod;
|
||
# CREATE USER dify_user WITH PASSWORD 'your-password';
|
||
# GRANT ALL PRIVILEGES ON DATABASE dify_prod TO dify_user;
|
||
|
||
# ========= Redis 配置 =========
|
||
# Dify 必须使用 Redis(不能用 Postgres-Only)
|
||
# ⚠️ 重要:在 Docker Compose 网络中,使用服务名而不是 localhost!
|
||
REDIS_HOST=redis
|
||
REDIS_PORT=6379
|
||
REDIS_PASSWORD=<strong-password>
|
||
|
||
# ========= 向量数据库配置 =========
|
||
# 使用 Weaviate(Docker Compose 自动启动)
|
||
VECTOR_STORE=weaviate
|
||
WEAVIATE_ENDPOINT=http://weaviate:8080
|
||
WEAVIATE_API_KEY=<生成一个随机字符串>
|
||
|
||
# ========= 存储配置 =========
|
||
# 使用阿里云 OSS(推荐)
|
||
STORAGE_TYPE=aliyun-oss
|
||
ALIYUN_OSS_BUCKET_NAME=<your-bucket-name>
|
||
ALIYUN_OSS_REGION=oss-cn-hangzhou
|
||
ALIYUN_OSS_ACCESS_KEY_ID=<your-access-key-id>
|
||
ALIYUN_OSS_ACCESS_KEY_SECRET=<your-access-key-secret>
|
||
|
||
# 或使用本地存储(不推荐)
|
||
# STORAGE_TYPE=local
|
||
|
||
# ========= LLM 配置 =========
|
||
# 默认 LLM 提供商(您可以在 Web UI 中添加多个)
|
||
DEFAULT_LLM_PROVIDER=openai-api-compatible
|
||
|
||
# DeepSeek API(示例)
|
||
DEEPSEEK_API_KEY=<your-deepseek-api-key>
|
||
DEEPSEEK_API_BASE=https://api.deepseek.com/v1
|
||
|
||
# ========= API 配置 =========
|
||
# API 服务地址(内网地址)
|
||
API_URL=http://<ECS内网IP>:5000
|
||
|
||
# Web 服务地址(如果需要访问 Dify Web UI)
|
||
WEB_API_URL=http://<ECS公网IP>
|
||
WEB_URL=http://<ECS公网IP>
|
||
|
||
# ========= 日志配置 =========
|
||
LOG_LEVEL=INFO
|
||
LOG_FILE=/data/logs/dify.log
|
||
|
||
# ========= 其他配置 =========
|
||
# 时区
|
||
TZ=Asia/Shanghai
|
||
|
||
# 是否开启 Debug
|
||
DEBUG=false
|
||
```
|
||
|
||
### 步骤 3:检查 Docker Compose 文件(建议使用官方配置)
|
||
|
||
```bash
|
||
# ⚠️ 强烈建议:不要手写 docker-compose.yaml!
|
||
# 直接使用官方文件,它包含了完整的架构(含 Nginx 网关)
|
||
|
||
# 查看官方配置
|
||
cat docker-compose.yaml
|
||
```
|
||
|
||
**官方架构包含的服务**:
|
||
|
||
```yaml
|
||
services:
|
||
# 1. nginx - 入口网关(必需!)
|
||
# 作用:路由请求到 API 和 Web,解决 CORS 问题
|
||
# /v1/* → API 服务
|
||
# /* → Web 服务
|
||
|
||
# 2. api - Dify API 服务
|
||
# 3. worker - 后台任务处理
|
||
# 4. web - Web 前端界面
|
||
# 5. redis - 缓存和任务队列(必需)
|
||
# 6. weaviate - 向量数据库
|
||
# 7. sandbox - 代码解释器(可选,但建议保留)
|
||
# 作用:如果在 Dify 中使用"代码解释器"功能
|
||
|
||
# 如果你删除了 nginx,会遇到:
|
||
# - 前端访问 API 时 CORS 跨域错误
|
||
# - API 路由 404 错误
|
||
|
||
# 如果你删除了 sandbox,会遇到:
|
||
# - "代码解释器"功能报错
|
||
```
|
||
|
||
**仅需修改的部分**(如果有特殊需求):
|
||
|
||
```yaml
|
||
# ⚠️ 安全配置:端口绑定到本地(防止公网访问)
|
||
services:
|
||
redis:
|
||
ports:
|
||
- "127.0.0.1:6379:6379" # ⚠️ 只监听本地,禁止公网访问
|
||
|
||
weaviate:
|
||
ports:
|
||
- "127.0.0.1:8080:8080" # ⚠️ 只监听本地,禁止公网访问
|
||
|
||
# 示例:如果需要外网访问 Web UI(通过Nginx)
|
||
nginx:
|
||
ports:
|
||
- "80:80" # HTTP(允许VPC内网访问)
|
||
- "443:443" # HTTPS(需要配置证书)
|
||
```
|
||
|
||
**⚠️ 安全红线:**
|
||
```yaml
|
||
# ❌ 绝对禁止(会被攻击)
|
||
services:
|
||
redis:
|
||
ports:
|
||
- "6379:6379" # 全世界可访问,Redis无密码会被清空
|
||
|
||
weaviate:
|
||
ports:
|
||
- "8080:8080" # 向量数据可能被窃取
|
||
|
||
api:
|
||
ports:
|
||
- "5000:5000" # 黑客可绕过后端消耗LLM额度
|
||
|
||
# ✅ 正确做法:绑定到127.0.0.1
|
||
services:
|
||
redis:
|
||
ports:
|
||
- "127.0.0.1:6379:6379" # 只能本机访问
|
||
```
|
||
|
||
**❌ 错误做法**:
|
||
```yaml
|
||
# 不要删减服务!尤其是 nginx
|
||
services:
|
||
api: ...
|
||
worker: ...
|
||
# ❌ 缺少 nginx(会导致前端无法访问 API)
|
||
```
|
||
|
||
**✅ 正确做法**:
|
||
```bash
|
||
# 保持官方 docker-compose.yaml 不变
|
||
# 只修改 .env 环境变量
|
||
# 如果确实需要调整,只添加端口映射等无害配置
|
||
```
|
||
|
||
### 步骤 4:创建必需目录
|
||
|
||
```bash
|
||
mkdir -p /data/dify/storage
|
||
mkdir -p /data/dify/logs
|
||
mkdir -p /data/dify/redis
|
||
mkdir -p /data/dify/weaviate
|
||
|
||
# 设置权限
|
||
chmod -R 755 /data/dify
|
||
```
|
||
|
||
### 步骤 5:初始化数据库
|
||
|
||
```bash
|
||
# 在 RDS 中创建 Dify 数据库(使用 psql 或 DBeaver)
|
||
# 连接到 RDS
|
||
psql -h <RDS内网地址> -U postgres -d postgres
|
||
|
||
# 执行
|
||
CREATE DATABASE dify_prod;
|
||
CREATE USER dify_user WITH PASSWORD 'your-password';
|
||
GRANT ALL PRIVILEGES ON DATABASE dify_prod TO dify_user;
|
||
\q
|
||
```
|
||
|
||
---
|
||
|
||
## 启动与验证
|
||
|
||
### 步骤 1:启动 Dify 服务
|
||
|
||
```bash
|
||
cd /data/dify/docker
|
||
|
||
# 拉取镜像(首次运行)
|
||
docker compose pull
|
||
|
||
# 启动服务(后台运行)
|
||
docker compose up -d
|
||
|
||
# 查看日志
|
||
docker compose logs -f api
|
||
|
||
# 等待服务启动(约30秒)
|
||
```
|
||
|
||
### 步骤 2:验证服务状态
|
||
|
||
```bash
|
||
# 1. 检查容器状态
|
||
docker compose ps
|
||
|
||
# 应该看到以下容器都是 Up 状态:
|
||
# - dify-api
|
||
# - dify-worker
|
||
# - dify-web (如果启用)
|
||
# - redis
|
||
# - weaviate
|
||
|
||
# 2. 检查 API 健康状态
|
||
curl http://localhost:5000/health
|
||
|
||
# 期望返回: {"status": "healthy"}
|
||
|
||
# 3. 检查 Weaviate 状态
|
||
curl http://localhost:8080/v1/meta
|
||
|
||
# 期望返回: JSON 格式的元数据
|
||
```
|
||
|
||
### 步骤 3:测试内网连通性
|
||
|
||
```bash
|
||
# 在 SAE 后端服务中测试(或在本地通过 VPN 连接到 VPC)
|
||
curl http://<ECS内网IP>:5000/health
|
||
|
||
# 如果返回 {"status": "healthy"},说明内网连通正常
|
||
```
|
||
|
||
### 步骤 4:初始化 Dify(首次部署)
|
||
|
||
1. **访问 Dify Web UI**(如果启用):
|
||
```
|
||
http://<ECS公网IP>
|
||
```
|
||
|
||
2. **创建管理员账号**:
|
||
- 邮箱:admin@your-domain.com
|
||
- 密码:<strong-password>
|
||
|
||
3. **配置 LLM 提供商**:
|
||
- 进入 "设置" → "模型提供商"
|
||
- 添加 DeepSeek/Qwen 等 API Key
|
||
|
||
### 步骤 5:配置后端环境变量
|
||
|
||
在 SAE 后端服务的环境变量中添加:
|
||
|
||
```bash
|
||
# Dify API 配置
|
||
DIFY_API_BASE=http://<ECS内网IP>:5000
|
||
DIFY_API_KEY=<从 Dify Web UI 中获取>
|
||
|
||
# 获取 API Key 的方法:
|
||
# Dify Web UI → 设置 → API Keys → 创建新密钥
|
||
```
|
||
|
||
---
|
||
|
||
## 配置说明
|
||
|
||
### 🔧 存储配置详解
|
||
|
||
#### 选项 1:阿里云 OSS(推荐)
|
||
|
||
**优势**:
|
||
- 无限扩展
|
||
- 高可用(99.9%)
|
||
- 与 SAE 内网通信,速度快
|
||
|
||
**配置**:
|
||
```bash
|
||
STORAGE_TYPE=aliyun-oss
|
||
ALIYUN_OSS_BUCKET_NAME=your-bucket-name
|
||
ALIYUN_OSS_REGION=oss-cn-hangzhou
|
||
ALIYUN_OSS_ACCESS_KEY_ID=<your-id>
|
||
ALIYUN_OSS_ACCESS_KEY_SECRET=<your-secret>
|
||
```
|
||
|
||
**注意**:
|
||
- OSS Bucket 必须和 ECS 在同一区域
|
||
- 建议使用内网 Endpoint(如:oss-cn-hangzhou-internal.aliyuncs.com)
|
||
- 设置合理的生命周期规则(如:30天后转冷存储)
|
||
|
||
#### 选项 2:本地存储(不推荐)
|
||
|
||
**缺点**:
|
||
- 磁盘空间有限
|
||
- 无法横向扩展
|
||
- 数据备份麻烦
|
||
|
||
**仅适用于**:测试环境或小规模部署
|
||
|
||
### 🔧 数据库配置详解
|
||
|
||
#### Dify 数据库与后端数据库分离
|
||
|
||
```
|
||
RDS PostgreSQL 实例
|
||
├─ 数据库 1: clinical_research (后端主数据库)
|
||
│ ├─ Schema: platform_schema
|
||
│ ├─ Schema: asl_schema
|
||
│ ├─ Schema: dc_schema
|
||
│ └─ ...
|
||
└─ 数据库 2: dify_prod (Dify 数据库)
|
||
├─ Schema: public
|
||
└─ ...
|
||
```
|
||
|
||
**优势**:
|
||
- 数据隔离(安全)
|
||
- 独立备份策略
|
||
- 避免资源竞争
|
||
|
||
**连接池配置**:
|
||
```bash
|
||
# Dify 的连接池较小(因为异步任务多)
|
||
DB_MAX_CONNECTIONS=20
|
||
```
|
||
|
||
### 🔧 Redis 配置说明
|
||
|
||
**为什么 Dify 必须用 Redis?**
|
||
- Dify 的任务队列依赖 Redis(Celery)
|
||
- 短期缓存(如:API 限流)
|
||
- 不能用 PostgreSQL 替代(与您的后端 Postgres-Only 架构不同)
|
||
|
||
**关键配置(避免连接失败)**:
|
||
```bash
|
||
# ⚠️ 致命错误警告:
|
||
# 在 .env 中,REDIS_HOST 必须设置为服务名 "redis"
|
||
# 不是 "localhost"!
|
||
|
||
# ❌ 错误写法(会导致 API 无法启动)
|
||
REDIS_HOST=localhost
|
||
|
||
# ✅ 正确写法(Docker Compose 网络中使用服务名)
|
||
REDIS_HOST=redis
|
||
|
||
# 原理:
|
||
# - 在 Docker Compose 中,容器之间通过服务名通信
|
||
# - localhost 指的是容器自己,不是 Redis 容器
|
||
# - redis 会被 Docker 网络解析为 Redis 容器的内网 IP
|
||
```
|
||
|
||
**安全加固**:
|
||
```bash
|
||
# 1. 设置强密码
|
||
REDIS_PASSWORD=<至少16位随机字符串>
|
||
|
||
# 2. 仅监听内网(docker-compose 中已配置)
|
||
# Redis 容器不暴露端口到主机,仅在 Docker 网络内可访问
|
||
|
||
# 3. 禁用危险命令(可选)
|
||
# 在 docker-compose.yaml 中修改 Redis 启动命令
|
||
command: >
|
||
redis-server
|
||
--requirepass ${REDIS_PASSWORD}
|
||
--rename-command CONFIG ""
|
||
--rename-command FLUSHALL ""
|
||
--rename-command FLUSHDB ""
|
||
```
|
||
|
||
---
|
||
|
||
## 监控与维护
|
||
|
||
### 📊 日志管理
|
||
|
||
#### 1. 查看实时日志
|
||
|
||
```bash
|
||
cd /data/dify/docker
|
||
|
||
# 查看所有服务日志
|
||
docker compose logs -f
|
||
|
||
# 查看特定服务日志
|
||
docker compose logs -f api
|
||
docker compose logs -f worker
|
||
```
|
||
|
||
#### 2. 日志文件位置
|
||
|
||
```
|
||
/data/dify/logs/
|
||
├─ api.log # API 服务日志
|
||
├─ worker.log # Worker 日志
|
||
└─ error.log # 错误日志
|
||
```
|
||
|
||
#### 3. 日志轮转配置
|
||
|
||
```bash
|
||
# 安装 logrotate(Ubuntu 默认已安装)
|
||
apt install logrotate
|
||
|
||
# 创建配置文件
|
||
cat > /etc/logrotate.d/dify <<EOF
|
||
/data/dify/logs/*.log {
|
||
daily
|
||
rotate 30
|
||
compress
|
||
delaycompress
|
||
notifempty
|
||
create 0644 root root
|
||
sharedscripts
|
||
postrotate
|
||
docker compose -f /data/dify/docker/docker-compose.yaml restart api worker
|
||
endscript
|
||
}
|
||
EOF
|
||
```
|
||
|
||
### 📊 性能监控
|
||
|
||
#### 1. 资源使用情况
|
||
|
||
```bash
|
||
# 查看容器资源占用
|
||
docker stats
|
||
|
||
# 查看磁盘使用
|
||
df -h /data
|
||
|
||
# 查看内存使用
|
||
free -h
|
||
```
|
||
|
||
#### 2. 数据库连接监控
|
||
|
||
```bash
|
||
# 连接到 RDS 查看 Dify 的连接数
|
||
psql -h <RDS内网地址> -U postgres -d dify_prod -c "
|
||
SELECT count(*)
|
||
FROM pg_stat_activity
|
||
WHERE datname = 'dify_prod';
|
||
"
|
||
```
|
||
|
||
#### 3. Redis 监控
|
||
|
||
```bash
|
||
# 连接到 Redis 容器
|
||
docker exec -it dify-redis redis-cli -a <REDIS_PASSWORD>
|
||
|
||
# 查看信息
|
||
INFO
|
||
INFO memory
|
||
INFO stats
|
||
```
|
||
|
||
### 🔄 定期维护任务
|
||
|
||
#### 每周任务
|
||
|
||
```bash
|
||
# 1. 清理 Docker 日志
|
||
truncate -s 0 $(docker inspect --format='{{.LogPath}}' dify-api)
|
||
truncate -s 0 $(docker inspect --format='{{.LogPath}}' dify-worker)
|
||
|
||
# 2. 清理无用的 Docker 资源
|
||
docker system prune -a --volumes -f
|
||
```
|
||
|
||
#### 每月任务
|
||
|
||
```bash
|
||
# 1. 数据库 VACUUM(在低峰期执行)
|
||
psql -h <RDS内网地址> -U dify_user -d dify_prod -c "VACUUM ANALYZE;"
|
||
|
||
# 2. 检查磁盘碎片
|
||
e2fsck -f /dev/vdb
|
||
|
||
# 3. 备份配置文件
|
||
tar -czf /backup/dify-config-$(date +%Y%m%d).tar.gz /data/dify/docker/.env
|
||
```
|
||
|
||
---
|
||
|
||
## 故障排查
|
||
|
||
### 🔥 常见问题
|
||
|
||
#### 问题 1:API 容器无法启动 - Redis 连接失败(高频错误)
|
||
|
||
**症状**:
|
||
```bash
|
||
docker compose ps
|
||
# 显示 dify-api 状态为 Exit 1 或不断重启
|
||
|
||
docker compose logs api
|
||
# 显示错误:
|
||
# redis.exceptions.ConnectionError: Error connecting to localhost:6379
|
||
# 或
|
||
# Cannot connect to Redis at localhost:6379
|
||
```
|
||
|
||
**根本原因**:
|
||
```bash
|
||
# ❌ .env 文件中配置错误
|
||
REDIS_HOST=localhost # 这是错的!
|
||
```
|
||
|
||
**解决方法**:
|
||
```bash
|
||
# 1. 编辑 .env 文件
|
||
nano /data/dify/docker/.env
|
||
|
||
# 2. 修改 REDIS_HOST
|
||
REDIS_HOST=redis # ✅ 改为服务名
|
||
|
||
# 3. 重启服务
|
||
docker compose down
|
||
docker compose up -d
|
||
|
||
# 4. 验证
|
||
docker compose logs api | grep -i redis
|
||
# 应该看到:Successfully connected to Redis
|
||
```
|
||
|
||
#### 问题 2:前端访问 API 报 CORS 错误
|
||
|
||
**症状**:
|
||
```
|
||
浏览器控制台报错:
|
||
Access to XMLHttpRequest at 'http://xxx/v1/xxx' from origin 'http://yyy'
|
||
has been blocked by CORS policy
|
||
```
|
||
|
||
**根本原因**:
|
||
- 缺少 Nginx 网关服务
|
||
- 或者 Nginx 配置错误
|
||
|
||
**解决方法**:
|
||
```bash
|
||
# 1. 确认 Nginx 容器是否运行
|
||
docker compose ps | grep nginx
|
||
|
||
# 2. 如果没有 Nginx,说明你删除了官方配置
|
||
# 解决方案:重新克隆官方仓库,使用完整的 docker-compose.yaml
|
||
|
||
cd /data/dify
|
||
rm -rf dify
|
||
git clone https://github.com/langgenius/dify.git
|
||
cd dify/docker
|
||
cp .env.example .env
|
||
# 重新配置 .env(参考前文)
|
||
docker compose up -d
|
||
```
|
||
|
||
#### 问题 3:容器无法启动 - 数据库连接失败
|
||
|
||
**症状**:
|
||
```bash
|
||
docker compose logs api
|
||
# 显示错误:
|
||
# could not connect to server: Connection refused
|
||
```
|
||
|
||
**排查步骤**:
|
||
```bash
|
||
# 1. 检查 RDS 白名单
|
||
# 阿里云控制台 → RDS → 数据安全性 → 白名单设置
|
||
# 确认添加了 ECS 的内网 IP
|
||
|
||
# 2. 检查 .env 配置
|
||
DB_HOST=<RDS内网地址> # 不是公网地址!
|
||
DB_PORT=5432
|
||
DB_NAME=dify_prod
|
||
DB_USERNAME=dify_user
|
||
DB_PASSWORD=<正确的密码>
|
||
|
||
# 3. 测试连接(在 ECS 上)
|
||
telnet <RDS内网地址> 5432
|
||
# 如果连接失败,检查安全组和白名单
|
||
```
|
||
|
||
#### 问题 4:服务运行一段时间后崩溃(OOM 内存溢出)
|
||
|
||
**症状**:
|
||
```bash
|
||
dmesg | grep -i kill
|
||
# 显示:Out of memory: Killed process xxx (dify-api)
|
||
|
||
docker compose ps
|
||
# 容器不断重启
|
||
```
|
||
|
||
**根本原因**:
|
||
- 2核4G 内存不足
|
||
- 没有配置 Swap 分区
|
||
|
||
**解决方法**:
|
||
```bash
|
||
# 1. 立即配置 Swap(如果之前没配置)
|
||
fallocate -l 4G /swapfile
|
||
chmod 600 /swapfile
|
||
mkswap /swapfile
|
||
swapon /swapfile
|
||
echo '/swapfile none swap sw 0 0' >> /etc/fstab
|
||
|
||
# 2. 验证 Swap 已启用
|
||
free -h
|
||
|
||
# 3. 重启服务
|
||
docker compose restart
|
||
|
||
# 4. 长期方案:升级 ECS 到 4核8G
|
||
```
|
||
|
||
#### 问题 2:API 返回 500 错误
|
||
|
||
**排查步骤**:
|
||
```bash
|
||
# 1. 查看 API 日志
|
||
docker compose logs -f api | grep ERROR
|
||
|
||
# 2. 检查数据库连接
|
||
docker exec -it dify-api sh
|
||
# 在容器内执行
|
||
python -c "
|
||
import psycopg2
|
||
conn = psycopg2.connect(
|
||
host='<RDS地址>',
|
||
database='dify_prod',
|
||
user='dify_user',
|
||
password='<password>'
|
||
)
|
||
print('Connection OK')
|
||
"
|
||
```
|
||
|
||
#### 问题 3:向量搜索失败
|
||
|
||
**排查步骤**:
|
||
```bash
|
||
# 1. 检查 Weaviate 状态
|
||
curl http://localhost:8080/v1/meta
|
||
|
||
# 2. 查看 Weaviate 日志
|
||
docker compose logs weaviate
|
||
|
||
# 3. 重建索引(最后手段)
|
||
# 在 Dify Web UI 中:设置 → 数据集 → 重新索引
|
||
```
|
||
|
||
#### 问题 4:内网连接失败(SAE 无法访问 ECS)
|
||
|
||
**排查步骤**:
|
||
```bash
|
||
# 1. 检查安全组规则
|
||
# 阿里云控制台 → ECS → 安全组 → 确认开放 5000 端口给 SAE 所在网段
|
||
|
||
# 2. 测试连通性(在 SAE 容器内执行)
|
||
telnet <ECS内网IP> 5000
|
||
|
||
# 3. 检查防火墙(在 ECS 上执行)
|
||
ufw status
|
||
# 如果启用了防火墙,添加规则:
|
||
ufw allow from <SAE网段> to any port 5000
|
||
```
|
||
|
||
### 🔄 重启服务
|
||
|
||
```bash
|
||
# 重启所有服务
|
||
cd /data/dify/docker
|
||
docker compose restart
|
||
|
||
# 重启单个服务
|
||
docker compose restart api
|
||
|
||
# 完全重建(如果修改了 docker-compose.yaml)
|
||
docker compose down
|
||
docker compose up -d
|
||
```
|
||
|
||
---
|
||
|
||
## 注意事项与禁忌
|
||
|
||
### ✅ 最佳实践
|
||
|
||
1. **定期备份**
|
||
```bash
|
||
# 每天自动备份(添加到 crontab)
|
||
0 2 * * * pg_dump -h <RDS地址> -U dify_user dify_prod | gzip > /backup/dify_$(date +\%Y\%m\%d).sql.gz
|
||
```
|
||
|
||
2. **监控磁盘空间**
|
||
```bash
|
||
# 设置告警(当 /data 使用率 > 80% 时通知)
|
||
# 可使用阿里云云监控服务
|
||
```
|
||
|
||
3. **使用内网域名**
|
||
```bash
|
||
# 为 ECS 设置内网域名(便于维护)
|
||
# 在 SAE 中配置 DIFY_API_BASE=http://dify.internal:5000
|
||
# 而不是写死 IP
|
||
```
|
||
|
||
4. **版本锁定**
|
||
```bash
|
||
# docker-compose.yaml 中使用具体版本号,不要用 latest
|
||
image: langgenius/dify-api:0.11.2 # ✅ 推荐
|
||
# image: langgenius/dify-api:latest # ❌ 禁止(可能导致不兼容)
|
||
```
|
||
|
||
### ❌ 绝对禁止
|
||
|
||
1. **禁止在 .env 中使用 REDIS_HOST=localhost**
|
||
```bash
|
||
# ❌ 致命错误(会导致服务启动失败)
|
||
REDIS_HOST=localhost
|
||
|
||
# ✅ 正确配置(在 Docker Compose 中使用服务名)
|
||
REDIS_HOST=redis
|
||
```
|
||
|
||
2. **禁止删减官方 docker-compose.yaml 的核心服务**
|
||
```bash
|
||
# ❌ 危险操作(会导致功能异常)
|
||
# - 删除 nginx → 前端 CORS 错误
|
||
# - 删除 worker → 异步任务失败
|
||
# - 删除 sandbox → 代码解释器功能失效
|
||
|
||
# ✅ 正确做法
|
||
# 使用官方完整配置,仅修改 .env 环境变量
|
||
```
|
||
|
||
3. **禁止在 2核4G 的 ECS 上不配置 Swap**
|
||
```bash
|
||
# ❌ 危险(极易 OOM 崩溃)
|
||
# 没有 Swap,内存用尽后服务直接被 Kill
|
||
|
||
# ✅ 必须配置 Swap
|
||
fallocate -l 4G /swapfile
|
||
chmod 600 /swapfile
|
||
mkswap /swapfile
|
||
swapon /swapfile
|
||
```
|
||
|
||
4. **禁止在生产环境使用 DEBUG=true**
|
||
```bash
|
||
# 会暴露敏感信息(如:API Key、数据库密码)
|
||
DEBUG=false # ✅
|
||
```
|
||
|
||
5. **禁止使用弱密码**
|
||
```bash
|
||
# 必须使用强密码(至少16位,包含大小写、数字、特殊字符)
|
||
SECRET_KEY=$(openssl rand -base64 32)
|
||
REDIS_PASSWORD=$(openssl rand -base64 24)
|
||
WEAVIATE_API_KEY=$(openssl rand -base64 24)
|
||
```
|
||
|
||
6. **禁止暴露 Redis 和 Weaviate 端口到公网**
|
||
```bash
|
||
# 官方配置默认不暴露这些端口,不要自己添加
|
||
# ❌ 危险配置
|
||
services:
|
||
redis:
|
||
ports:
|
||
- "6379:6379" # 会被攻击!
|
||
|
||
# ✅ 正确做法:仅在 Docker 网络内访问
|
||
```
|
||
|
||
7. **禁止直接修改数据库**
|
||
```bash
|
||
# 不要手动修改 Dify 数据库的表结构或数据
|
||
# 必须通过 Dify API 或 Web UI 操作
|
||
```
|
||
|
||
8. **禁止在 ECS 上运行其他无关服务**
|
||
```bash
|
||
# 这台 ECS 专门用于 Dify,不要部署其他应用
|
||
# 避免资源竞争和安全风险
|
||
```
|
||
|
||
### ⚠️ 重要提醒
|
||
|
||
1. **数据主权**
|
||
- 所有向量数据和文档都存储在您的 ECS 和 OSS 上
|
||
- 定期检查数据备份的完整性
|
||
|
||
2. **成本控制**
|
||
- ECS 按量付费 vs 包年包月(根据实际情况选择)
|
||
- 监控 OSS 存储量和流量(避免超出预算)
|
||
|
||
3. **升级策略**
|
||
```bash
|
||
# 升级 Dify 版本前的步骤:
|
||
# 1. 备份数据库
|
||
# 2. 在测试环境验证
|
||
# 3. 选择业务低峰期升级
|
||
# 4. 做好回滚准备
|
||
```
|
||
|
||
4. **私有化部署路径**
|
||
```
|
||
当前架构 → 直接复制到客户环境
|
||
├─ 导出 docker-compose.yaml
|
||
├─ 导出 .env(敏感信息替换)
|
||
├─ 打包为安装脚本(一键部署)
|
||
└─ 提供《私有化部署手册》
|
||
```
|
||
|
||
---
|
||
|
||
## 📚 附录
|
||
|
||
### A. 生成强密码的方法
|
||
|
||
```bash
|
||
# 方法 1: 使用 openssl
|
||
openssl rand -base64 32
|
||
|
||
# 方法 2: 使用 pwgen
|
||
pwgen -s 32 1
|
||
|
||
# 方法 3: 使用 Python
|
||
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
|
||
```
|
||
|
||
### B. Dify API 常用端点
|
||
|
||
```bash
|
||
# 健康检查
|
||
GET http://<ECS内网IP>:5000/health
|
||
|
||
# 创建数据集
|
||
POST http://<ECS内网IP>:5000/v1/datasets
|
||
Headers: Authorization: Bearer <API_KEY>
|
||
Body: {"name": "test-dataset"}
|
||
|
||
# 上传文档
|
||
POST http://<ECS内网IP>:5000/v1/datasets/{dataset_id}/documents
|
||
Headers: Authorization: Bearer <API_KEY>
|
||
Body: (multipart/form-data)
|
||
|
||
# 语义检索
|
||
POST http://<ECS内网IP>:5000/v1/datasets/{dataset_id}/retrieve
|
||
Headers: Authorization: Bearer <API_KEY>
|
||
Body: {"query": "xxx", "top_k": 5}
|
||
```
|
||
|
||
### C. 相关文档链接
|
||
|
||
- [Dify 官方文档](https://docs.dify.ai/)
|
||
- [Docker Compose 文档](https://docs.docker.com/compose/)
|
||
- [Weaviate 文档](https://weaviate.io/developers/weaviate)
|
||
- [阿里云 ECS 文档](https://help.aliyun.com/product/25365.html)
|
||
- [阿里云 OSS 文档](https://help.aliyun.com/product/31815.html)
|
||
|
||
---
|
||
|
||
**文档维护**:
|
||
- 如有问题或建议,请联系技术负责人
|
||
- 最后更新:2025-12-13
|
||
- 下次审查:2025-03-13
|
||
|