首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >从零搭建 Dify AI 平台:一次跌宕起伏的部署之旅

从零搭建 Dify AI 平台:一次跌宕起伏的部署之旅

原创
作者头像
一只牛博
修改2025-11-25 23:31:13
修改2025-11-25 23:31:13
3970
举报
文章被收录于专栏:AIAI

本文记录了在 CentOS Stream 9 服务器上使用 Docker Compose 部署 Dify 的完整过程,包括踩过的所有坑和解决方案。

前言

最近公司想搭建一套私有化的 AI 应用平台,选来选去最终选了 Dify。官方文档看起来很简单,docker-compose up -d 一把梭,但实际部署时却遇到了一堆问题。这篇文章不会告诉你"五分钟快速部署"的美梦,而是分享真实的部署过程和那些让人抓狂的错误。

服务器环境

  • 系统:CentOS Stream 9(香港节点)
  • 配置:16 核 CPU + 16GB 内存 + 20Mbps 带宽
  • 硬盘:40GB 系统盘(没错,就这么小!)
  • Docker:29.0.1
  • Docker Compose:v2.40.3
Docker 版本信息
Docker 版本信息

Dify 架构解析

在开始部署前,先理解 Dify 是怎么工作的。它不是一个单体应用,而是由多个容器协同工作:

image-20251125092325365
image-20251125092325365

各容器的职责

1. dify-nginx:流量指挥官

这是 Dify 内部的反向代理,负责把请求分发到正确的服务:

  • / → dify-web(前端页面)
  • /api → dify-api(API 接口)
  • /console/api → dify-api(控制台 API)
  • /v1 → dify-api(应用 API)

关键点:它不直接暴露到外网,而是通过 Nginx Proxy Manager(NPM)访问。这样做的好处是 SSL 证书、域名都由 NPM 统一管理。

2. dify-api & dify-worker:业务大脑

这两个容器用的是同一个镜像 langgenius/dify-api,但通过环境变量 MODE 区分角色:

  • dify-apiMODE=api):处理 HTTP 请求,负责用户交互
  • dify-workerMODE=worker):处理异步任务,比如训练模型、处理文件

它们通过 Redis 的消息队列通信:

image-20251125092448451
image-20251125092448451
3. Redis:三重身份

Redis 在 Dify 中扮演三个角色:

  1. 缓存:Session、用户权限等热数据
  2. 消息队列:Celery 任务队列(DB 0、1、2)
  3. 分布式锁:防止并发操作冲突

配置中使用了不同的 DB 隔离:

代码语言:javascript
复制
REDIS_DB: 0                      # Session 存储
CELERY_BROKER_URL: redis://:密码@redis:6379/1   # 任务队列
CELERY_RESULT_BACKEND: redis://:密码@redis:6379/2  # 结果存储
4. PostgreSQL:数据仓库

Dify 用了两个数据库

  • dify:主业务数据(用户、应用、对话历史等)
  • dify_plugin:插件系统专用数据库

这个设计很巧妙,插件系统完全隔离,不会影响主业务。

5. Weaviate:向量大脑

这是个向量数据库,负责存储文档的 Embedding(向量表示)。当你问 AI 问题时,流程是这样的:

image-20251125103617961
image-20251125103617961
6. plugin-daemon:扩展引擎

这是 Dify 0.4+ 版本引入的插件系统守护进程。它做两件事:

  • 管理插件:安装、卸载、版本控制
  • 运行插件:提供隔离的 Python 运行环境

它有两个端口:

  • 5002:HTTP API(给 dify-api 调用)
  • 5003:远程调试端口(gnet 协议)
7. sandbox & ssrf_proxy:安全卫士
  • sandbox:代码沙箱,用户可以在工作流中运行 Python 代码,但被严格隔离
  • ssrf_proxy:SSRF 防护代理,防止代码访问内网敏感服务
image-20251125103629709
image-20251125103629709

目录结构设计

部署前先规划好目录,这能避免很多麻烦:

代码语言:javascript
复制
/acowbo/docker-compose/dify/
├── docker-compose.yml       # 核心编排文件
├── .env                     # 环境变量(包含密钥!)
├── nginx/                   # Nginx 配置
│   ├── nginx.conf          # 主配置
│   ├── proxy.conf          # 代理设置
│   └── conf.d/
│       └── dify.conf       # 路由规则
├── volumes/                 # 持久化数据
│   ├── app/storage/        # 用户上传文件
│   ├── postgres/data/      # 数据库数据
│   ├── redis/data/         # Redis 持久化
│   ├── weaviate/data/      # 向量数据
│   ├── plugin-daemon/      # 插件文件
│   ├── sandbox/dependencies/ # 沙箱依赖
│   └── nginx/logs/         # 访问日志
├── cleanup-docker.sh        # 清理脚本
├── logrotate-dify          # 日志轮转
└── init.sh                 # 初始化脚本
目录结构
目录结构

部署过程:踩坑实录

坑1:镜像版本不存在

官方文档可能会过时。我一开始配置的是:

代码语言:javascript
复制
image: langgenius/dify-api:1.10.0

启动时报错:Error response from daemon: manifest for langgenius/dify-api:1.10.0 not found

去 Docker Hub 一看,根本没有 1.10.0 这个 tag!

解决方案:用 latest 标签,或者去 Docker Hub 确认版本。

代码语言:javascript
复制
image: langgenius/dify-api:latest

坑2:路径硬编码问题

我参考的文档里路径是 /opt/dify/dify-build,但我实际部署在 /acowbo/docker-compose/dify。结果 logrotate-dify 文件里写死了路径:

代码语言:javascript
复制
/opt/dify/dify-build/volumes/nginx/logs/*.log {
    # 配置...
}

导致日志轮转找不到文件。

经验教训

  1. docker-compose.yml 里尽量用相对路径(./volumes
  2. 系统级配置文件要手动改成实际路径
  3. 部署前用 grep -r "你的路径" 全局检查

坑3:网络配置的大坑

我想让 Dify 和 Nginx Proxy Manager(NPM)共享网络 acowbo_network,一开始这样配置:

代码语言:javascript
复制
networks:
  acowbo_network:
    name: acowbo_network
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16

启动时警告:network with name acowbo_network exists but was not created for project "dify"

原因是 NPM 已经创建了这个网络,Dify 不能重复创建。

正确做法

代码语言:javascript
复制
networks:
  acowbo_network:
    external: true  # 使用已存在的外部网络

坑4:端口 80 冲突

启动时报错:Bind for 0.0.0.0:80 failed: port is already allocated

因为 NPM 已经占用了 80 端口!其实 Dify 的 Nginx 根本不需要暴露端口,通过容器名访问就行。

解决方案

代码语言:javascript
复制
nginx:
  # ports:  # 注释掉,不暴露端口
  #   - "80:80"

NPM 中配置反向代理:

代码语言:javascript
复制
Domain: dify.acowbo.com
Forward to: http://dify-nginx:80  # 用容器名

流程图:

image-20251125103649764
image-20251125103649764

坑5:Nginx 配置错误

我把 map 指令放在了 proxy.conf 里:

代码语言:javascript
复制
# proxy.conf(错误位置)
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

启动报错:nginx: [emerg] "map" directive is not allowed here

map 指令只能放在 http 块,而 proxy.conf 是被 includeserver 块的。

正确做法

代码语言:javascript
复制
# nginx.conf
http {
    # map 指令必须在这里
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    include /etc/nginx/proxy.conf;
    include /etc/nginx/conf.d/*.conf;
}

坑6:plugin-daemon 的连环坑

这是最折磨人的部分,花了几个小时调试。

问题1:容器反复重启

日志显示:[PANIC]Invalid configuration: plugin remote installing host is empty

缺少环境变量。查官方文档和源码后,发现需要配置:

代码语言:javascript
复制
environment:
  SERVER_KEY: ${SECRET_KEY}  # 认证密钥
  SERVER_PORT: 5002          # HTTP API 端口
  PLUGIN_REMOTE_INSTALLING_HOST: 0.0.0.0  # 调试服务地址
  PLUGIN_REMOTE_INSTALLING_PORT: 5003     # 调试端口
  PLUGIN_WORKING_PATH: /app/storage/cwd   # 工作目录

  # 数据库配置
  DB_DATABASE: dify_plugin   # 注意:不是 dify!
问题2:端口配置混乱

plugin-daemon 有两个服务:

  • GIN HTTP 服务(端口 5002):给 dify-api 调用的 REST API
  • gnet 远程调试服务(端口 5003):供开发者远程调试插件

我一开始把两个端口搞混了,导致 API 连接失败。

关键配置

代码语言:javascript
复制
# plugin-daemon
environment:
  SERVER_PORT: 5002  # GIN HTTP 端口
  PLUGIN_REMOTE_INSTALLING_PORT: 5003  # gnet 调试端口

# dify-api
environment:
  PLUGIN_DAEMON_URL: http://plugin-daemon:5002  # 连接 HTTP 端口

日志验证:

代码语言:javascript
复制
[gnet] Launching gnet with 8 event-loops, listening on: tcp://0.0.0.0:5003
[GIN] 200 | GET "/health/check"  # HTTP 服务在 5002
问题3:环境变量名错误

这个最坑!我配置了 PLUGIN_DAEMON_ENDPOINT,但 Dify 代码里认的是 PLUGIN_DAEMON_URL

测试:

代码语言:javascript
复制
docker exec dify-api python -c \
  "from configs import dify_config; print(dify_config.PLUGIN_DAEMON_ENDPOINT)"

# 报错:AttributeError: 'DifyConfig' object has no attribute 'PLUGIN_DAEMON_ENDPOINT'
# Did you mean: 'PLUGIN_DAEMON_TIMEOUT'?

正确的环境变量:

代码语言:javascript
复制
# .env 文件
PLUGIN_DAEMON_URL=http://plugin-daemon:5002  # 不是 ENDPOINT!
PLUGIN_DAEMON_KEY=你的密钥
问题4:认证失败(401)

配置都对了,但请求返回 401 Unauthorized。

测试发现认证方式不对:

代码语言:javascript
复制
# 错误(Bearer Token)
curl -H "Authorization: Bearer 密钥" http://plugin-daemon:5002/plugin/xxx
# 401 Unauthorized

# 正确(X-Api-Key)
curl -H "X-Api-Key: 密钥" http://plugin-daemon:5002/plugin/xxx
# 200 OK

查看源码确认了认证方式:

代码语言:javascript
复制
# api/core/plugin/impl/base.py
prepared_headers["X-Api-Key"] = dify_config.PLUGIN_DAEMON_KEY

坑7:数据库未初始化

第一次访问页面,所有 /console/api/ 接口都返回 400:

代码语言:javascript
复制
sqlalchemy.exc.ProgrammingError: relation "dify_setups" does not exist

原因是数据库表还没创建。

解决方案

代码语言:javascript
复制
# 运行数据库迁移
docker exec dify-api flask db upgrade

# 重启服务
docker compose restart api worker

然后访问 https://你的域名/install 完成初始化,创建管理员账号。

坑8:日志文件爆满

40GB 系统盘很容易被日志撑爆!必须做日志管理。

策略1:限制容器日志
代码语言:javascript
复制
services:
  api:
    logging:
      driver: "json-file"
      options:
        max-size: "50m"   # 单文件最大 50MB
        max-file: "2"     # 保留 2 个文件
        compress: "true"  # 压缩旧日志
策略2:Nginx 日志轮转
代码语言:javascript
复制
# /etc/logrotate.d/dify
/acowbo/docker-compose/dify/volumes/nginx/logs/*.log {
    daily              # 每天轮转
    rotate 7           # 保留 7 天
    maxsize 100M       # 超过 100M 强制轮转
    compress           # 压缩
    delaycompress      # 延迟一天压缩
    missingok          # 文件不存在不报错
    notifempty         # 空文件不轮转
    postrotate
        docker exec dify-nginx nginx -s reopen
    endscript
}

部署:

代码语言:javascript
复制
sudo cp logrotate-dify /etc/logrotate.d/dify
sudo chmod 644 /etc/logrotate.d/dify
sudo logrotate -d /etc/logrotate.d/dify  # 测试
策略3:定时清理 Docker
代码语言:javascript
复制
# cleanup-docker.sh
docker system prune -f --volumes --filter "until=168h"  # 删除 7 天前的数据
docker image prune -a -f --filter "until=168h"

# crontab
0 3 * * 0 /acowbo/docker-compose/dify/cleanup-docker.sh

完整配置文件

docker-compose.yml(核心部分)

代码语言:javascript
复制
services:
  api:
    image: langgenius/dify-api:latest
    container_name: dify-api
    restart: always
    environment:
      TZ: Asia/Hong_Kong  # 时区
      MODE: api
      SECRET_KEY: ${SECRET_KEY}

      # 数据库
      DB_USERNAME: ${DB_USERNAME:-postgres}
      DB_PASSWORD: ${DB_PASSWORD}
      DB_HOST: postgres
      DB_PORT: 5432
      DB_DATABASE: dify

      # Redis
      REDIS_HOST: redis
      REDIS_PORT: 6379
      REDIS_PASSWORD: ${REDIS_PASSWORD}

      # 插件配置(关键!)
      PLUGIN_ENABLED: true
      PLUGIN_DAEMON_URL: http://plugin-daemon:5002  # 注意是 URL 不是 ENDPOINT
      PLUGIN_DAEMON_KEY: ${SECRET_KEY}

    volumes:
      - ./volumes/app/storage:/app/api/storage
    networks:
      - acowbo_network
    depends_on:
      - postgres
      - redis

  plugin-daemon:
    image: langgenius/dify-plugin-daemon:0.4.1-local
    container_name: dify-plugin-daemon
    restart: always
    environment:
      TZ: Asia/Hong_Kong

      # 服务配置
      SERVER_PORT: 5002  # HTTP API
      SERVER_KEY: ${SECRET_KEY}

      # 调试配置
      PLUGIN_REMOTE_INSTALLING_HOST: 0.0.0.0
      PLUGIN_REMOTE_INSTALLING_PORT: 5003  # gnet 调试端口
      PLUGIN_WORKING_PATH: /app/storage/cwd

      # 数据库(独立库)
      DB_USERNAME: ${DB_USERNAME:-postgres}
      DB_PASSWORD: ${DB_PASSWORD}
      DB_HOST: postgres
      DB_PORT: 5432
      DB_DATABASE: dify_plugin  # 注意:不是 dify

      # Redis
      REDIS_HOST: redis
      REDIS_PORT: 6379
      REDIS_PASSWORD: ${REDIS_PASSWORD}

    volumes:
      - ./volumes/plugin-daemon:/app/storage
    networks:
      - acowbo_network
    depends_on:
      - postgres

networks:
  acowbo_network:
    external: true  # 与 NPM 共享网络

.env(记得改密钥!)

代码语言:javascript
复制
# ========================================
# 密钥配置(必须修改!)
# ========================================
SECRET_KEY=<生成随机密钥>
DB_PASSWORD=<生成随机密码>
REDIS_PASSWORD=<生成随机密码>
WEAVIATE_API_KEY=<生成随机密钥>

# ========================================
# 域名配置
# ========================================
CONSOLE_WEB_URL=https://your_domain.com
CONSOLE_API_URL=https://your_domain.com
APP_WEB_URL=https://your_domain.com

# ========================================
# 插件配置(关键!)
# ========================================
PLUGIN_ENABLED=true
PLUGIN_DAEMON_URL=http://plugin-daemon:5002  # 不是 ENDPOINT
PLUGIN_DAEMON_KEY=${SECRET_KEY}

# ========================================
# 数据库性能优化(16GB 内存)
# ========================================
POSTGRES_SHARED_BUFFERS=2GB
POSTGRES_EFFECTIVE_CACHE_SIZE=8GB
REDIS_MAXMEMORY=512mb

生成随机密钥

代码语言:javascript
复制
# SECRET_KEY(64 字符)
openssl rand -base64 48

# 密码(32 字符)
openssl rand -base64 24

启动流程

详细步骤

代码语言:javascript
复制
# 1. 创建目录并上传文件
mkdir -p /acowbo/docker-compose/dify
cd /acowbo/docker-compose/dify

# 上传 docker-compose.yml, .env, nginx/ 等文件

# 2. 生成密钥并修改 .env
vi .env
# 修改所有密钥和域名

# 3. 创建数据目录
./init.sh  # 或手动创建 volumes/ 下的目录

# 4. 确保 Docker 网络存在(如果用外部网络)
docker network create acowbo_network || true

# 5. 启动服务
docker compose up -d
启动过程
启动过程
代码语言:javascript
复制
# 6. 查看状态
docker compose ps
启动成功
启动成功
代码语言:javascript
复制
# 7. 初始化数据库(第一次部署)
docker exec dify-api flask db upgrade

# 8. 重启确保配置生效
docker compose restart api worker

# 9. 访问初始化页面
https://你的域名/install

NPM 反向代理配置

Details 标签页

代码语言:javascript
复制
Domain Names: dify.acowbo.com
Scheme: http
Forward Hostname/IP: dify-nginx
Forward Port: 80

☑ Cache Assets
☑ Block Common Exploits
☑ Websockets Support  ← 必须勾选!

SSL 标签页

代码语言:javascript
复制
SSL Certificate: Request a new SSL Certificate

☑ Force SSL
☑ HTTP/2 Support
☑ HSTS Enabled

Email: your@email.com
☑ I Agree to the Let's Encrypt Terms of Service

Advanced 标签页

代码语言:javascript
复制
# AI 响应可能较慢,增加超时
proxy_read_timeout 600s;
proxy_connect_timeout 600s;
proxy_send_timeout 600s;

# 支持文件上传
client_max_body_size 100M;

# 传递真实 IP
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;

请求流程全景图

image-20251125103853985
image-20251125103853985

故障排查

1. 容器不停重启

代码语言:javascript
复制
# 查看日志
docker logs 容器名 --tail 100

# 常见原因:
# - 环境变量缺失
# - 数据库连接失败
# - 端口被占用
# - 配置文件语法错误

2. 页面访问 502

代码语言:javascript
复制
# 检查容器状态
docker compose ps

# 检查网络连通性
docker exec dify-nginx curl http://api:5001/health
docker exec dify-nginx curl http://web:3000/

# 检查 NPM 到 dify-nginx
docker exec npm容器名 curl http://dify-nginx/health

3. Plugin 相关 400 错误

这是最常见的错误,检查清单:

代码语言:javascript
复制
# 1. 确认环境变量名正确
docker exec dify-api env | grep PLUGIN

# 应该看到:
# PLUGIN_DAEMON_URL=http://plugin-daemon:5002  (不是 ENDPOINT)
# PLUGIN_DAEMON_KEY=...

# 2. 测试连接
docker exec dify-api curl -H "X-Api-Key: 你的密钥" \
  http://plugin-daemon:5002/health/check

# 3. 查看 plugin-daemon 日志
docker logs dify-plugin-daemon --tail 50

# 4. 确认数据库存在
docker exec dify-postgres psql -U postgres -l | grep plugin

4. 数据库相关错误

代码语言:javascript
复制
# relation "xxx" does not exist
# → 运行迁移
docker exec dify-api flask db upgrade

# password authentication failed
# → 检查 .env 中的 DB_PASSWORD

# could not connect to server
# → 检查 postgres 容器是否启动
docker compose ps postgres

性能优化建议

1. PostgreSQL 调优(16GB 内存)

代码语言:javascript
复制
# .env
POSTGRES_SHARED_BUFFERS=2GB       # 共享缓冲区
POSTGRES_EFFECTIVE_CACHE_SIZE=8GB  # 系统缓存
POSTGRES_WORK_MEM=16MB             # 排序/JOIN 内存
POSTGRES_MAINTENANCE_WORK_MEM=512MB  # 维护操作内存
POSTGRES_MAX_CONNECTIONS=200       # 最大连接数

2. Redis 优化

代码语言:javascript
复制
REDIS_MAXMEMORY=512mb              # 最大内存
REDIS_MAXMEMORY_POLICY=allkeys-lru # 淘汰策略

3. API Worker 调优

代码语言:javascript
复制
# Celery 并发
CELERY_WORKER_CLASS=gevent  # 使用协程
CELERY_MAX_WORKERS=8        # 根据 CPU 核心数

监控与维护

日志查看技巧

代码语言:javascript
复制
# 实时查看所有容器日志
docker compose logs -f

# 只看特定服务
docker compose logs -f api worker

# 查看最近 100 行
docker logs dify-api --tail 100

# 查看最近 5 分钟
docker logs dify-api --since 5m

# 过滤错误
docker logs dify-api 2>&1 | grep -i error

备份策略

代码语言:javascript
复制
#!/bin/bash
# backup.sh

BACKUP_DIR="/backup/dify-$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR

# 备份数据库
docker exec dify-postgres pg_dump -U postgres dify > $BACKUP_DIR/dify.sql
docker exec dify-postgres pg_dump -U postgres dify_plugin > $BACKUP_DIR/dify_plugin.sql

# 备份向量数据
docker exec dify-weaviate curl -X POST http://localhost:8080/v1/backups/filesystem \
  -H "Content-Type: application/json" \
  -d '{"id":"backup-'$(date +%Y%m%d)'"}'

# 备份上传文件
tar -czf $BACKUP_DIR/storage.tar.gz volumes/app/storage/

# 删除 7 天前的备份
find /backup -name "dify-*" -mtime +7 -exec rm -rf {} \;

定时任务:

代码语言:javascript
复制
# crontab -e
0 2 * * * /acowbo/docker-compose/dify/backup.sh

磁盘空间监控

40GB 系统盘必须时刻盯着:

代码语言:javascript
复制
# 查看磁盘使用
df -h

# 查看 Docker 占用
docker system df

# 查看各目录大小
du -sh volumes/*

# 查看日志大小
du -sh volumes/nginx/logs/
du -sh /var/lib/docker/containers/*/

告警脚本:

代码语言:javascript
复制
#!/bin/bash
# disk-alert.sh

USAGE=$(df / | tail -1 | awk '{print $5}' | sed 's/%//')
if [ $USAGE -gt 80 ]; then
    echo "磁盘使用率: $USAGE% - 告警!" | mail -s "Dify 磁盘告警" admin@example.com
    # 清理 Docker
    docker system prune -f
fi

安全加固

1. 修改默认端口

代码语言:javascript
复制
# NPM 管理端口别用 81
ports:
  - "10811:81"  # 用随机高端口

2. 防火墙规则

代码语言:javascript
复制
# 只开放必要端口
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --permanent --add-port=443/tcp
firewall-cmd --permanent --add-port=10811/tcp  # NPM 管理
firewall-cmd --reload

# 限制 NPM 管理端口访问
firewall-cmd --permanent --add-rich-rule='
  rule family="ipv4"
  source address="你的IP"
  port port="10811" protocol="tcp"
  accept'

3. 定期更新

代码语言:javascript
复制
# 拉取最新镜像
docker compose pull

# 重启服务
docker compose up -d

# 清理旧镜像
docker image prune -a -f --filter "until=168h"

成果展示

部署完成后的界面:

Dify 界面
Dify 界面

访问地址:https://your_domain.com

功能验证清单:

  • ✅ 用户注册/登录
  • ✅ 创建应用
  • ✅ 上传文档训练
  • ✅ 对话测试
  • ✅ 插件安装
  • ✅ Workflow 编排
  • ✅ API 调用

总结与经验

这次部署从下午 1 点折腾到晚上 9 点,踩了无数坑。总结几点经验:

1. 充分理解架构

不要一上来就 docker-compose up,先搞清楚每个容器的作用和依赖关系。Dify 的微服务架构并不复杂,但容器间的交互需要弄明白。

2. 环境变量是魔鬼细节

  • 变量名要精确(PLUGIN_DAEMON_URL vs PLUGIN_DAEMON_ENDPOINT
  • 密钥要一致(API 的 KEY 和 plugin-daemon 的 SERVER_KEY)
  • 别忘了非标准端口(plugin-daemon 的 5002 和 5003)

3. 日志是最好的老师

遇到问题别慌,看日志:

代码语言:javascript
复制
docker logs 容器名 --tail 100 --follow

90% 的问题日志里都有答案。

4. 官方文档可能过时

尤其是 plugin-daemon 这种新功能,文档更新不及时。遇到问题要:

  1. 看官方 GitHub Issues
  2. 查看源码(Python/Golang)
  3. docker exec 进容器探索

5. 40GB 磁盘真的够呛

建议:

  • 挂载对象存储(OSS)存用户文件
  • 日志必须轮转
  • 定期清理 Docker 缓存

6. 备份是必须的

数据库没备份,睡觉都不踏实。至少做到:

  • 每天自动备份数据库
  • 每周全量备份
  • 备份文件异地存储

写在最后

Dify 是个很棒的 AI 应用平台,但部署确实不算"开箱即用"。希望这篇文章能帮到想要自建的朋友,少踩点坑。

如果你也遇到了部署问题,欢迎交流讨论。记住:日志是你最好的朋友,耐心是你最大的武器

参考资料

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 服务器环境
  • Dify 架构解析
    • 各容器的职责
      • 1. dify-nginx:流量指挥官
      • 2. dify-api & dify-worker:业务大脑
      • 3. Redis:三重身份
      • 4. PostgreSQL:数据仓库
      • 5. Weaviate:向量大脑
      • 6. plugin-daemon:扩展引擎
      • 7. sandbox & ssrf_proxy:安全卫士
  • 目录结构设计
  • 部署过程:踩坑实录
    • 坑1:镜像版本不存在
    • 坑2:路径硬编码问题
    • 坑3:网络配置的大坑
    • 坑4:端口 80 冲突
    • 坑5:Nginx 配置错误
    • 坑6:plugin-daemon 的连环坑
      • 问题1:容器反复重启
      • 问题2:端口配置混乱
      • 问题3:环境变量名错误
      • 问题4:认证失败(401)
    • 坑7:数据库未初始化
    • 坑8:日志文件爆满
      • 策略1:限制容器日志
      • 策略2:Nginx 日志轮转
      • 策略3:定时清理 Docker
  • 完整配置文件
    • docker-compose.yml(核心部分)
    • .env(记得改密钥!)
  • 启动流程
    • 详细步骤
  • NPM 反向代理配置
    • Details 标签页
    • SSL 标签页
    • Advanced 标签页
  • 请求流程全景图
  • 故障排查
    • 1. 容器不停重启
    • 2. 页面访问 502
    • 3. Plugin 相关 400 错误
    • 4. 数据库相关错误
  • 性能优化建议
    • 1. PostgreSQL 调优(16GB 内存)
    • 2. Redis 优化
    • 3. API Worker 调优
  • 监控与维护
    • 日志查看技巧
    • 备份策略
    • 磁盘空间监控
  • 安全加固
    • 1. 修改默认端口
    • 2. 防火墙规则
    • 3. 定期更新
  • 成果展示
  • 总结与经验
    • 1. 充分理解架构
    • 2. 环境变量是魔鬼细节
    • 3. 日志是最好的老师
    • 4. 官方文档可能过时
    • 5. 40GB 磁盘真的够呛
    • 6. 备份是必须的
  • 写在最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档