Agent 上云部署实战(上):从 GitHub 到 Linux,用 Dify 跑通中间件、域名和 HTTPS
摘要:Agent 在笔记本能运行,不代表云服务器可以直接访问。本文以 Dify 官方发布仓库为例,在 Ubuntu 上串起 Docker、PostgreSQL、Redis、向量库、模型配置、端口映射、云安全组、Nginx 与 HTTPS,最后给出分层验收、故障定位和备份升级方法。
服务器上的容器显示 Running,浏览器却打不开;管理页面能登录,Agent 一调用模型就超时。这两种问题发生在不同层,不能靠"把所有端口打开"一起解决。
这篇文章的目标很具体:在一台 Linux 或云服务器上部署真实的 Agent 应用平台,让它经过受控入口被访问,并能完成一次真实模型与工具调用。 不从零编造一个平台,也不把 uvicorn --reload 当生产部署。
系列导航与阅读范围
- 上篇:Dify 平台型部署,覆盖服务器、中间件、端口、域名、HTTPS 与运维。
- 下篇:《Agent 上云部署实战(下):部署 LangGraph 官方 ReAct 项目,打通镜像、中间件与 API》,解释代码型 Agent 的部署路线。
两篇关联链接在公开发布后补充。本文以 Ubuntu 24.04 LTS、Docker Engine、Compose v2 为命令环境;其他 Linux 发行版需替换安装与防火墙命令。调用远程模型,不部署本地推理引擎,通常不需要 GPU。
**版本边界:**资料核对日期为 2026-10-11,Dify 示例固定为仓库发布标签 1.17.1。不同版本的服务名、环境文件和 Agent API 有差异,不要拿旧版教程变量硬套新版。单机部署适合学习和小规模验证,不承诺高可用或任何并发指标。
文章目录
- [Agent 上云部署实战(上):从 GitHub 到 Linux,用 Dify 跑通中间件、域名和 HTTPS](#Agent 上云部署实战(上):从 GitHub 到 Linux,用 Dify 跑通中间件、域名和 HTTPS)
-
- 系列导航与阅读范围
- 一、从官方仓库确认:我们究竟部署哪些东西
-
- [1.1 中间件各自解决什么问题](#1.1 中间件各自解决什么问题)
- [1.2 为什么 API 启了,知识库仍然处理不了](#1.2 为什么 API 启了,知识库仍然处理不了)
- [二、准备 Linux 服务器:先解决资源和出站网络](#二、准备 Linux 服务器:先解决资源和出站网络)
-
- [2.1 安装 Docker Engine 和 Compose v2](#2.1 安装 Docker Engine 和 Compose v2)
- [三、克隆固定发布版本,而不是直接部署 main](#三、克隆固定发布版本,而不是直接部署 main)
-
- [3.1 不要把新版 .env.example 当成旧版"大杂烩"](#3.1 不要把新版 .env.example 当成旧版“大杂烩”)
- [3.2 首次部署生成独立密钥,成对配置不能漏](#3.2 首次部署生成独立密钥,成对配置不能漏)
- 四、端口设计:先只允许服务器本机访问
-
- [4.1 把公网、宿主和容器三个地址空间分开](#4.1 把公网、宿主和容器三个地址空间分开)
- [4.2 覆盖端口,不能"加一条更安全的映射"就算完成](#4.2 覆盖端口,不能“加一条更安全的映射”就算完成)
- [4.3 中间件随官方 Compose 部署,先逐个验收](#4.3 中间件随官方 Compose 部署,先逐个验收)
- [五、云安全组、Linux 防火墙与 SSH 隧道](#五、云安全组、Linux 防火墙与 SSH 隧道)
-
- [5.1 安全组规则如何填写](#5.1 安全组规则如何填写)
- [5.2 没有域名时,先用 SSH 隧道,不裸露安装页面](#5.2 没有域名时,先用 SSH 隧道,不裸露安装页面)
- [六、域名、宿主 Nginx 与 HTTPS:把正式入口接起来](#六、域名、宿主 Nginx 与 HTTPS:把正式入口接起来)
-
- [6.1 配好 DNS 和 Dify 外部 URL](#6.1 配好 DNS 和 Dify 外部 URL)
- [6.2 先配置 HTTP 证书校验入口](#6.2 先配置 HTTP 证书校验入口)
- [6.3 拿到证书后替换为完整反向代理配置](#6.3 拿到证书后替换为完整反向代理配置)
- [七、部署了平台之后,还要配置一个能执行工具的 Agent](#七、部署了平台之后,还要配置一个能执行工具的 Agent)
-
- [7.1 模型 Key 不等于 Dify 应用 API Key](#7.1 模型 Key 不等于 Dify 应用 API Key)
- [7.2 做一个可验收的任务,不只问"你好"](#7.2 做一个可验收的任务,不只问“你好”)
- [7.3 接本机模型或内部工具时,localhost 最容易误配](#7.3 接本机模型或内部工具时,localhost 最容易误配)
- 八、访问异常怎样按层定位
-
- [8.1 先在服务器本机查,再从你的电脑查](#8.1 先在服务器本机查,再从你的电脑查)
- [8.2 什么才叫部署验收通过](#8.2 什么才叫部署验收通过)
- 九、持久化、备份和升级:不要把容器当数据库备份
-
- [9.1 必须备份的不只 PostgreSQL](#9.1 必须备份的不只 PostgreSQL)
- [9.2 升级应先恢复演练,再切换镜像](#9.2 升级应先恢复演练,再切换镜像)
- 十、选型与下一步
- 参考来源与说明
一、从官方仓库确认:我们究竟部署哪些东西
项目地址:langgenius/dify。部署入口不是仓库根目录的一条 Python 命令,而是 docker/ 中的官方 Compose、环境模板、Nginx 模板和持久化目录。固定版本部署说明
不要只复制一个 YAML:其中挂载了本地配置文件,缺少 nginx/、ssrf_proxy/ 等目录可能导致挂载失败。完整克隆仓库,再进入 docker/。
1.1 中间件各自解决什么问题
| 组件 | 在这次部署中做什么 | 是否开放公网端口 |
|---|---|---|
| Web 与 API | 管理界面、应用配置和请求入口 | 只经统一网关访问 |
| Worker、定时调度进程 | 执行后台处理、定时任务 | 不需要 |
| PostgreSQL | 应用、用户、知识库等结构化数据 | 不需要 |
| Redis | 缓存、消息与后台任务相关通信 | 不需要 |
| Weaviate | 本文选定的知识检索向量存储 | 不需要 |
| 文件存储 | 用户上传内容及生成产物 | 通过授权文件接口访问 |
| 插件服务与沙箱 | 模型/工具插件及受限制代码环境 | 普通使用不开放调试口 |
| Nginx | 统一转发界面和 API 请求 | 公开入口使用 80/443 |
这里的向量库是 Weaviate,不需要再安装 Milvus、Qdrant、Elasticsearch 全家桶。本文默认文件存储也不依赖 MinIO。如果选择其他后端,再根据对应环境模板补充服务和配置。
1.17.1 还有独立 Agent backend、local sandbox 和相关代理网络。不要依据早期版本的容器数量判断新版是否"多启动了无用服务"。固定版本 Compose
1.2 为什么 API 启了,知识库仍然处理不了
源码启动入口依据运行模式分别启动 API、Celery Worker 或调度进程。它们可以使用同一应用镜像,却承担不同职责。文档上传后的后台处理不应仅凭 API 首页能打开就判定正常。启动脚本
验收要分别看:入口是否通、数据库是否连接、Worker 是否执行、插件是否初始化、模型是否可达。Running 只是进程状态,不是业务成功。
二、准备 Linux 服务器:先解决资源和出站网络
本文建议先用已有测试服务器验证,不要仅凭教程购买配置。可从 4 vCPU、8 GiB 内存、60 GiB 可用 SSD 的测试机器起步,这是本文保守的起始建议,不是官方最低要求或性能保证。文档规模、插件数量、并发和本地模型都会改变资源需求。
先检查环境:
bash
cat /etc/os-release
uname -m
free -h
df -h
sudo ss -lntp
最后一条很重要:如果宿主 Nginx、宝塔或其他应用已经占用 80/443,就不能让 Dify 容器再占同一端口。本文采用"宿主 Nginx → 回环端口 → Dify 内部 Nginx",避免冲突。
服务器需能访问 GitHub、镜像仓库、模型供应商以及所选插件源。GitHub 下载成功不代表模型域名也可访问;模型服务器返回 401 至少说明 TLS 和 HTTP 已通,但不说明你的账号具备调用资格。
bash
curl -I --connect-timeout 10 https://github.com
# 将下一行替换为你的模型供应商 HTTPS 域名,不带密钥
curl -I --connect-timeout 10 https://api.openai.com
不要通过关闭 TLS 校验处理证书报错。先查系统时间、CA 证书、DNS 和企业代理。也不要随便使用陌生镜像源并把模型密钥交给它。
2.1 安装 Docker Engine 和 Compose v2
在全新 Ubuntu 上,按 Docker 官方 Ubuntu 安装指引 配置官方 apt 仓库。下面用 Ubuntu 24.04 的 noble,其他版本不要照抄发行版代号:
bash
sudo apt-get update
sudo apt-get install -y ca-certificates curl git openssl python3
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
创建 /etc/apt/sources.list.d/docker.sources,内容为:
text
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: noble
Components: stable
Architectures: amd64
Signed-By: /etc/apt/keyrings/docker.asc
ARM64 机器把 Architectures 改成 arm64,并确认应用镜像支持该架构。有既有 Docker/Podman 时先阅读官方冲突包说明,不要在生产机上盲目卸载。
bash
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker
sudo docker version
sudo docker compose version
sudo docker run --rm hello-world
本文一直使用 sudo docker,避免为方便把所有用户加入接近 root 权限的 docker 组。后面的端口覆盖使用 !override,需要 Compose v2.24.4 或更新。单纯版本较新的 Docker CLI 不代表 Compose 插件也符合要求。
三、克隆固定发布版本,而不是直接部署 main
选择一个没有同名目录的路径,例如当前用户下的 agent-services:
bash
mkdir -p "$HOME/agent-services"
cd "$HOME/agent-services"
git clone --branch 1.17.1 --depth 1 https://github.com/langgenius/dify.git dify-1.17.1
cd dify-1.17.1/docker
cp .env.example .env
chmod 600 .env
git rev-parse HEAD
记录最后输出的提交标识。固定仓库标签不一定固定所有镜像:某些依赖镜像仍可能使用 latest。正式交付还应记录实际镜像 digest,做安全审查并测试升级,不能只记录 Dify 标签。
3.1 不要把新版 .env.example 当成旧版"大杂烩"
当前发布版本的入口模板与可选 envs/*.env.example 分工:默认启动参数在根模板,高级配置按服务分组。不要从网上复制另一版本的千行 .env,它可能漏掉新增的安全键,还可能包含已弃用配置。
保留同版本模板,通过编辑器修改 .env。下面是需要检查和修改的键,不是可独立替代整份模板的文件 :环境模板
dotenv
DB_TYPE=postgresql
VECTOR_STORE=weaviate
WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED=false
NGINX_HTTPS_ENABLED=false
SERVER_CONSOLE_API_URL=http://api:5001
最后一个是 Web 在容器内访问 API 的地址,不要改成 http://localhost:5001。此处 NGINX_HTTPS_ENABLED=false 只表示内部这一跳走 HTTP,公网 TLS 在宿主 Nginx 终止,后面会配置。
3.2 首次部署生成独立密钥,成对配置不能漏
创建 configure_first_install.py,在首次启动前运行。脚本只替换模板中的已存在键,遇到版本不匹配就停止;不打印秘密,也不用于已有实例随意轮换密钥:
python
from pathlib import Path
import os
import secrets
p = Path('.env')
text = p.read_text()
values = {k: secrets.token_hex(32) for k in (
'SECRET_KEY', 'DB_PASSWORD', 'REDIS_PASSWORD',
'PLUGIN_DAEMON_KEY', 'PLUGIN_DIFY_INNER_API_KEY',
'DIFY_AGENT_API_TOKEN', 'DIFY_AGENT_SERVER_SECRET_KEY',
'DIFY_AGENT_LOCAL_SANDBOX_AUTH_TOKEN')}
sandbox = secrets.token_hex(32)
vector = secrets.token_hex(32)
values.update({
'SANDBOX_API_KEY': sandbox,
'CODE_EXECUTION_API_KEY': sandbox,
'WEAVIATE_API_KEY': vector,
'WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS': vector,
'WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED': 'false',
'CELERY_BROKER_URL': 'redis://:' + values['REDIS_PASSWORD'] + '@redis:6379/1',
})
found = set()
lines = []
for line in text.splitlines():
key = line.partition('=')[0]
if key in values:
line = key + '=' + values[key]
found.add(key)
lines.append(line)
missing = set(values) - found
if missing:
raise SystemExit('Template keys missing: ' + ', '.join(sorted(missing)))
temporary = p.with_suffix('.new')
temporary.write_text('\n'.join(lines) + '\n')
os.chmod(temporary, 0o600)
temporary.replace(p)
print('First-install secrets configured; values were not printed.')
bash
python3 configure_first_install.py
这些只是这条部署路径中明确处理的密钥,不代表以后增加任何存储后端都不需要新凭证。hex 字符串也避免密码中的 @、:、$ 干扰 Redis URI 和 Compose 展开。
**已有数据库不能靠改 DB_PASSWORD 更新密码。**数据库镜像的初始化密码通常只在空数据目录首次创建时生效。已有实例需要协调数据库密码变更和应用配置,不能重新跑上述脚本。SECRET_KEY 改变也可能影响现有会话和签名。
四、端口设计:先只允许服务器本机访问

4.1 把公网、宿主和容器三个地址空间分开
本文固定访问路径为:
text
浏览器 https://agent.example.com:443
→ 云安全组允许 443
→ 宿主 Nginx :443
→ 宿主 127.0.0.1:8088
→ Dify Nginx 容器 :80
→ web:3000 / api:5001
→ PostgreSQL、Redis、向量库与插件服务
agent.example.com 是示例域名,必须换成你自己的。公网 IP 在云平台上可能是 NAT 映射,并不一定出现在 ip addr 中,不能因此把服务绑定到一个不存在的地址。
| 端口 | 所属位置 | 外部访问政策 |
|---|---|---|
| 22 | Linux SSH | 仅管理员公网 IP 或 VPN |
| 80 | 宿主 Nginx | 证书校验与跳转,可按实际方案调整 |
| 443 | 宿主 Nginx | 正式 HTTPS 入口 |
| 8088 | 宿主回环 → Dify 网关 | 不向公网开放 |
| 3000、5001 | Docker 中的 Web/API | 不做公网映射 |
| 5432、6379、8080 | Docker 中间件 | 不做公网映射 |
| 5003 | 插件调试 | 本教程删除映射 |
4.2 覆盖端口,不能"加一条更安全的映射"就算完成
在 docker/ 下新建 compose.linux.yaml:
yaml
services:
nginx:
ports: !override
- "127.0.0.1:8088:80"
plugin_daemon:
ports: !reset []
Compose 普通列表覆盖可能按规则合并,导致原来的公网映射还在。这里明确替换 Nginx 所有原端口并移除插件调试映射。Compose 合并规则
**后续每条部署命令都要带这两个 -f。**如果配置时带覆盖文件,启动时忘了,就可能重新暴露默认端口。
bash
sudo docker compose -f docker-compose.yaml -f compose.linux.yaml config --quiet
sudo docker compose -f docker-compose.yaml -f compose.linux.yaml config --services
sudo docker compose -f docker-compose.yaml -f compose.linux.yaml pull
sudo docker compose -f docker-compose.yaml -f compose.linux.yaml up -d
sudo docker compose -f docker-compose.yaml -f compose.linux.yaml ps
不带 --quiet 的 config 会展开密钥,不要把它的完整输出复制到公开 Issue 或博客。ps 中应看到 Nginx 的 127.0.0.1:8088->80/tcp,而不是 0.0.0.0:8088。
4.3 中间件随官方 Compose 部署,先逐个验收
bash
sudo docker compose -f docker-compose.yaml -f compose.linux.yaml \
exec -T db_postgres pg_isready -U postgres -d dify
sudo docker compose -f docker-compose.yaml -f compose.linux.yaml \
exec -T redis redis-cli ping
sudo docker compose -f docker-compose.yaml -f compose.linux.yaml \
logs --tail 80 api worker plugin_daemon
curl -I http://127.0.0.1:8088
本文默认数据库用户为模板的 postgres;改了用户就一起改检查命令。Redis 容器模板设置了 REDISCLI_AUTH,无需把密码打在终端命令上。预期 Redis 返回 PONG,页面可能是 200 或重定向;这些是验收标准,不是本文伪造的运行截图。
第一次拉取镜像和安装插件可能较慢。日志出现明确失败时再定位原因,不要反复重启把证据冲掉。
五、云安全组、Linux 防火墙与 SSH 隧道
5.1 安全组规则如何填写
云厂商界面不同,但你要配置的是入站 TCP、端口范围、来源地址 :22 只允许管理员出口 IP /32;80/443 按公开网站或内部系统需求允许。若只给团队用,443 也可限制公司出口或 VPN。
不要为了浏览器打不开而开放 1-65535。没有 PostgreSQL 和 Redis 公网映射时,也不需要在安全组里允许 5432/6379。IPv6 是另一条访问路径,如果配置了 AAAA 记录,同样需要检查 IPv6 监听和安全组。
Ubuntu 的 UFW 示例,先确认 SSH 实际端口并保持第二个 SSH 会话:
bash
# 替换 203.0.113.10;这是文档保留示例地址,不是你的管理员 IP
sudo ufw allow from 203.0.113.10 to any port 22 proto tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw status verbose
# 确认现有策略不会锁死 SSH 后,再启用
sudo ufw enable
已有防火墙规则需人工审查,以上新增规则不会自动移除旧的"全网开放 SSH"。Docker 端口发布与防火墙规则有交互,不能只看 UFW 状态就断言容器安全 。限制发布地址、检查 Docker 规则,并从外部测试。Docker 防火墙说明、端口发布说明
5.2 没有域名时,先用 SSH 隧道,不裸露安装页面
在你的电脑执行:
bash
ssh -N -L 8088:127.0.0.1:8088 deploy@YOUR_SERVER_IP
然后打开本机 http://127.0.0.1:8088/install。这样浏览器通过 SSH 加密隧道访问服务器回环端口。SSH 自己连不上时,先修正登录用户、密钥、安全组或 SSH 端口,而不是修改 Dify。
首次安装管理员账户完成之前,建议保持入口只通过隧道访问,避免别人先访问未初始化页面。本文不会替你在真实服务器上修改密码或开放端口。
六、域名、宿主 Nginx 与 HTTPS:把正式入口接起来
6.1 配好 DNS 和 Dify 外部 URL
为你拥有的域名配置 A 记录指向云服务器公网 IPv4。不要添加不能工作的 AAAA 记录。解析传播期间可以分别检查本机 DNS 和外部 DNS。
在 .env 中修改下面这些外部 URL,保留内部 API 地址:
dotenv
CONSOLE_API_URL=https://agent.example.com
CONSOLE_WEB_URL=https://agent.example.com
SERVICE_API_URL=https://agent.example.com
APP_API_URL=https://agent.example.com
APP_WEB_URL=https://agent.example.com
FILES_URL=https://agent.example.com
TRIGGER_URL=https://agent.example.com
NEXT_PUBLIC_SOCKET_URL=wss://agent.example.com
ENDPOINT_URL_TEMPLATE=https://agent.example.com/e/{hook_id}
SERVER_CONSOLE_API_URL=http://api:5001
这里使用同一域名,不额外制造跨域、Cookie 跨子域和证书配置难题。模板中的 URL 大多是 origin,不要凭感觉都加 /v1;对外应用 API 的具体路径由应用 API 文档决定。
通过隧道测试时,最好先完成初始化,再切换上述正式域名;否则浏览器可能请求尚未配置的正式地址。
6.2 先配置 HTTP 证书校验入口
bash
sudo apt-get install -y nginx certbot
sudo install -d -m 0755 /var/www/acme
创建 /etc/nginx/conf.d/agent.conf,先写下列 HTTP 配置。不要覆盖同名的已有业务文件:
nginx
server {
listen 80;
server_name agent.example.com;
location /.well-known/acme-challenge/ {
root /var/www/acme;
}
location / { return 404; }
}
bash
sudo nginx -t
sudo systemctl reload nginx
sudo certbot certonly --webroot -w /var/www/acme -d agent.example.com
把域名换成你的,按提示提供邮箱并自行确认协议。HTTP-01 校验要求证书机构能从互联网访问该域名的 80 端口;如果公司要求完全不开放 80,应改用可信 DNS 插件的 DNS-01 流程,而不是关闭证书校验。
6.3 拿到证书后替换为完整反向代理配置
map 位于 http 上下文。Ubuntu 默认 conf.d/*.conf 在此上下文载入;自定义 Nginx 安装需自行确认:
nginx
map $http_upgrade $agent_connection {
default upgrade;
'' close;
}
server {
listen 80;
server_name agent.example.com;
location /.well-known/acme-challenge/ { root /var/www/acme; }
location / { return 301 https://$host$request_uri; }
}
server {
listen 443 ssl;
server_name agent.example.com;
ssl_certificate /etc/letsencrypt/live/agent.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/agent.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
client_max_body_size 100m;
location / {
proxy_pass http://127.0.0.1:8088;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $agent_connection;
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
}
}
bash
sudo nginx -t
sudo systemctl reload nginx
sudo docker compose -f docker-compose.yaml -f compose.linux.yaml up -d
curl -I https://agent.example.com
完整保留路径非常重要:Dify 内部 Nginx 会把不同路径转到 Web/API。不要只代理一个自猜的 /api 然后发现文件预览、插件端点或 WebSocket 都失效。官方路由模板
SSE 需要两层代理都不缓冲;WebSocket 需要 Upgrade 头;上传需要两层都允许足够大小。proxy_read_timeout 是相邻读取的空闲超时,不是"任务一定允许运行一小时"。网关之外的 CDN、负载均衡也可能更早断开。Nginx 代理指令
证书更新后还需要 Nginx 重新加载证书。检查发行版安装的自动续期任务,并设置成功续期后的 reload hook;仅运行一次 certbot 不代表永远没有过期风险。
例如用编辑器创建 /etc/letsencrypt/renewal-hooks/deploy/reload-agent-nginx.sh,内容如下,然后设置可执行权限:
bash
#!/bin/sh
/usr/sbin/nginx -t && /bin/systemctl reload nginx
bash
sudo chmod 750 /etc/letsencrypt/renewal-hooks/deploy/reload-agent-nginx.sh
实际命令路径以 command -v nginx、command -v systemctl 为准。hook 只在续期成功后加载证书,不替代自动续期任务。
bash
sudo certbot renew --dry-run
systemctl list-timers --all | grep certbot
七、部署了平台之后,还要配置一个能执行工具的 Agent
7.1 模型 Key 不等于 Dify 应用 API Key
模型 Key 是 Dify 调用模型供应商的凭证;应用 API Key 是你的业务后端调用 Dify 某个应用的凭证;管理员登录密码则用于控制台。这三个不能混用,也都不要写在公开截图里。
通过 HTTPS 控制台完成管理员初始化后,在模型供应商配置中添加你有权限使用的服务,选择支持所需工具调用能力的模型并完成连接测试。必要时填写供应商明确提供的 API Base,不要把普通网页地址当 API 地址。
7.2 做一个可验收的任务,不只问"你好"
建议创建一个检索型 Agent:提示词要求它"回答前先检索,给出来源,信息不足时说明";连接一个已配置凭证的只读搜索工具;明确最大迭代与费用预算。先在调试界面确认出现工具调用,再保存应用版本。
如果使用知识库,先上传一个不含敏感信息的小文档,配置 embedding 模型,确认索引完成。聊天模型能连接不代表 embedding 模型也已配置;一直等待索引时,应同时看 Worker、embedding API 和向量库,不是只重启 Web。
当前 Dify 包含不同 Agent 类型。传统 Agent-chat/Chatbot 使用聊天消息接口,新版 Agent 有自己的 API 表面,不能把 /v1/chat-messages 宣称为所有 Agent 的通用入口 。以应用页面显示的 API 示例和类型为准。API 入门与应用类型
下面命令用于传统聊天兼容应用,先在终端交互读取应用 Key,避免把真实 Key 写进 Shell 历史:
bash
read -r -s -p 'Dify app API key: ' DIFY_APP_KEY
printf '\n'
curl -N --fail-with-body https://agent.example.com/v1/chat-messages \
-H "Authorization: Bearer $DIFY_APP_KEY" \
-H 'Content-Type: application/json' \
--data '{"inputs":{},"query":"请检索并说明 Docker Compose 的用途,附上来源", "response_mode":"streaming", "conversation_id":"", "user":"deployment-check-001"}'
unset DIFY_APP_KEY
inputs 要包含你实际应用要求的变量,不能保证任意应用都接受空对象。通过流式事件中的结束/错误信息判定成功,不只看最初 HTTP 200。聊天消息接口
**服务器出站调用模型与用户入站访问网站是两个方向。**安全组开放 443 入站,不会自动修好服务器出站 DNS、代理或模型额度。
7.3 接本机模型或内部工具时,localhost 最容易误配
在 API 容器内,127.0.0.1 指该 API 容器,不是 Linux 宿主。若模型是同一 Compose 内的服务,用服务名与容器端口;若在另一网络,建立受控网络连接;若在宿主,用可达的宿主私网地址并限制来源。不要为方便把模型服务和 SSH 一起公开。
Linux 上 host.docker.internal 不一定默认存在。添加 host-gateway 映射只能解决名称,还需要宿主服务实际监听可达地址和防火墙允许。SSRF 代理也可能拒绝私网目的地,应针对必要地址添加最小允许规则,不要取消所有限制。
八、访问异常怎样按层定位
8.1 先在服务器本机查,再从你的电脑查
bash
# Linux 服务器上
curl -I http://127.0.0.1:8088
sudo ss -lntp
sudo docker compose -f docker-compose.yaml -f compose.linux.yaml ps
sudo nginx -t
sudo journalctl -u nginx --since '10 minutes ago' --no-pager
# 你自己的电脑上
curl -I https://agent.example.com
| 现象 | 优先检查 | 不应做的动作 |
|---|---|---|
| 本机 8088 也不通 | 容器退出、映射、80/8088 冲突、初始化日志 | 先开放所有公网端口 |
| 本机通,外网超时 | DNS、公网 IP、安全组、宿主监听、防火墙 | 给数据库开公网权限 |
| Connection refused | 目标端口无监听、访问了错误地址 | 只调整模型提示词 |
| HTTPS 证书错误 | 域名是否匹配、有效期、证书链、时间 | 用 -k 长期跳过验证 |
| 502 | 上游连接、服务健康、Docker DNS、配置路径 | 固定一个会变化的容器 IP |
| 页面能开,接口 CORS 错 | 外部 URL、协议、跨域和 Cookie | 永久设置任意来源且忽略凭证 |
| 413 | 两层代理与应用上传限制 | 无限扩大限制且不设配额 |
| 回答最后一次性出现 | 两层缓冲、CDN、模型是否真流式 | 宣称 SSE 已实现却不看事件 |
| 文档永远在排队 | Worker、Redis、embedding、向量库 | 只重启浏览器 |
| 插件安装失败 | 插件源/PyPI 出站、证书、签名、存储权限 | 关闭签名验证解决所有问题 |
502 时优先用服务名检查连接、重新加载网关并排查 DNS,不把动态容器 IP 硬编码进长期配置。错误日志可能包含路径或输入,应脱敏后再分享。
8.2 什么才叫部署验收通过
至少保留四类真实证据:容器健康与映射、HTTPS 页面、工具调用轨迹、外部 API 请求完成。重启后的数据仍在,也要单独检查。以下留给你在自己的服务器实际执行后补图:
【截图占位:Compose 服务及回环端口映射,隐藏敏感变量】
【截图占位:HTTPS 控制台和模型连接测试,隐藏 Key】
【截图占位:一次真实 Agent 工具调用及 API 完成事件】
九、持久化、备份和升级:不要把容器当数据库备份
9.1 必须备份的不只 PostgreSQL
结构化数据库、向量库、上传文件、插件存储、环境配置和新增命名卷都需要纳入清单。先检查实际挂载:
bash
sudo docker compose -f docker-compose.yaml -f compose.linux.yaml config --volumes
sudo docker volume ls
volumes/ 是宿主绑定目录,但某些服务使用 Docker 命名卷。只打包这个目录不一定覆盖全部数据。不要使用 docker compose down -v 做普通升级,它会删除相关命名卷。
PostgreSQL 逻辑备份示例,先创建受保护的备份目录:
bash
umask 077
mkdir -p ./backups
sudo docker compose -f docker-compose.yaml -f compose.linux.yaml \
exec -T db_postgres pg_dump -U postgres -d dify -Fc \
> ./backups/dify-$(date +%Y%m%d-%H%M%S).dump
这是单库备份,插件数据库及其他数据库需另行覆盖;运行中分别备份数据库和文件并不自动提供跨存储一致性。小规模完整备份可以安排停写窗口、停止应用与相关写入、使用正确的数据库备份或存储快照机制,再逐一覆盖绑定目录和命名卷。不要复制正在写入的 PostgreSQL 数据目录并称为可靠备份。
备份要加密、异地保存、设置保留期限,并用隔离环境演练恢复。将 .env 放进未加密的公开对象存储,就是把全套密钥公开。
9.2 升级应先恢复演练,再切换镜像
阅读目标版本 Release 与迁移说明,备份数据和配置,建立新版本目录,按新模板迁移必要键,再测试数据库迁移、插件和知识库。数据迁移后能否退回旧程序,要看 schema 兼容性,不能只 git checkout 旧标签就保证回滚。
单机的 restart: always 只改善进程退出和宿主重启后的恢复,不会给你第二台服务器,更不会自动修好损坏数据。正式多用户服务还需容量、日志轮转、错误告警、配额及灾难恢复计划。
十、选型与下一步
想让团队通过 UI 管理知识库、工具和 Agent,Dify 是更直接的起点。它的运维成本来自完整平台的多个状态服务,而不是一份 Python 文件。
如果你希望图节点、工具执行和 API 协议都由代码控制,下篇基于官方 ReAct 仓库完成镜像构建和服务部署。两种路线都要面对公网入口、中间件和密钥,只是业务编排的入口不同。
先完成这条最小闭环:本机回环访问 → SSH 隧道初始化 → 模型与工具成功 → 域名 HTTPS → 外部 API 验收 → 备份恢复。前一阶段失败时,留在该层定位,不用扩大端口权限掩盖问题。
参考来源与说明
资料采集与核对日期:2026-10-11。配置以固定发布版本为基准;本文给出部署流程与验收标准,不虚构你的云服务器启动结果。
- Dify Release
- 官方部署快速开始
- 固定版本部署目录
- 固定版本环境模板
- Docker Ubuntu 安装
- Docker Compose 合并与端口覆盖
- Docker 防火墙
- Dify API 指引
配图为生成式中文示意图,完整提示词随本地 Markdown 保存,实际端口以配置和 docker compose ps 为准。