This repository has been archived on 2026-08-12. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Cyrene/docs/deploy/docker-compose.md
T
AskaEth 46441335c0 refactor: 统一 .env 配置 — 合并 backend/.env + .docker.env 到根目录
- Go 服务 godotenv.Load("../.env") → godotenv.Load("../../.env")
- ethend.sh/config.js 读取路径改为根目录 .env
- 删除 .docker.env.example 和 backend/.env.example,统一为 .env.example
- Docker compose 默认读取根 .env,无需 --env-file
- 同步更新全部文档

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 10:12:54 +08:00

236 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Docker Compose 生产部署
## 快速开始
```bash
# 1. 配置环境变量
cp .env.example .env
# 编辑 .env,填入真实的 API Key 和密码
# 有域名时设置 DOMAIN=your-domain.com
# 2. 启动所有服务
docker compose up -d
# 3. 查看状态
docker compose ps
docker compose logs -f
```
## 服务清单
| 服务 | 端口 | 说明 |
|------|------|------|
| caddy | 80 / 443 | 反向代理,自动 HTTPS |
| gateway | 8080 (内部) | API 网关 |
| ai-core | 8081 (内部) | AI 核心 |
| memory-service | 8091 (内部) | 记忆检索 |
| voice-service | 8093 (内部) | 语音识别 |
| iot-debug-service | 8083 (内部) | IoT 调试 |
| ethend | 9090 (外部) | 管理控制台 |
| postgres | 5432 (内部) | 数据库 (pgvector/pg16) |
| redis | 6379 (内部) | 缓存 |
| qdrant | 6333 (内部) | 向量数据库 |
| minio | 9000 (内部) | 对象存储 |
| searxng | 8080 (内部) | 搜索引擎 |
## 架构分层
```
Internet
┌────────────────────────────────────┐
│ Caddy (:80/:443) │ ← 反向代理层
│ TLS 自动签发 · WebSocket 路由 │
└────────────┬───────────────────────┘
┌─────▼──────┐
│ Gateway │ ← API 网关层
│ :8080 │ 唯一后端入口
└──┬───┬───┬─┘
│ │ │
┌────▼┐ ┌▼───▼──┐ ┌────────────┐
│AI │ │Memory │ │Voice/IoT/ │ ← 业务服务层
│Core │ │:8091 │ │ethend │
│:8081│ └───────┘ └────────────┘
└──┬──┘
┌────▼───────────────────────────┐
│ Postgres · Redis · Qdrant · MinIO│ ← 基础设施层
└────────────────────────────────┘
```
12 个容器通过内部 Docker 网络通信(服务名即主机名)。仅 Caddy 和 ethend 向宿主机暴露端口。
---
## 各服务详解
### 反向代理层
**Caddy** — 唯一对外入口,监听 `${CADDY_HTTP_PORT:-80}``${CADDY_HTTPS_PORT:-443}`
路由规则(由 [Caddyfile](../../Caddyfile) 定义):
| 路径 | 转发目标 | 说明 |
|------|----------|------|
| `/ws/*` | gateway:8080 | WebSocket 实时推送 |
| `/api/*` | gateway:8080 | REST API(含 X-Forwarded-For |
| 其他 | 内置响应 | 前端占位页 |
- `DOMAIN` 非空时,Caddy 自动从 Let's Encrypt 签发 TLS 证书
- `DOMAIN` 为空时仅 HTTP`:80` 模式)
### API 网关层
**Gateway** (`:8080`) — 核心枢纽,所有客户端请求经由此处。启动要求 PostgreSQL 和 Redis 均通过健康检查。
功能:JWT 认证、用户注册/登录、WebSocket Hub、限流、CORS、消息排队。
关键 env
- `JWT_SECRET` + `INTERNAL_SERVICE_TOKEN` — 缺失会导致 **panic**
- `ADMIN_USERNAME` + `ADMIN_PASSWORD` — 首次启动时自动创建管理员账号
- `ALLOWED_ORIGINS` — 跨域白名单,需包含 ethend 端口和前端地址
### 业务服务层
**AI-Core** (`:8081`) — LLM 编排核心:人设注入、多子会话调度、工具调用、后台思考。依赖 PostgreSQL 健康。
**Memory Service** (`:8091`) — 记忆 CRUD + 语义检索 + 衰减 + 自动提取。依赖 PostgreSQL 健康。
**Voice Service** (`:8093`) — DashScope 云 STT + whisper.cpp 本地 ASR。无启动依赖。
**IoT Debug Service** (`:8083`) — 8 个模拟智能家居设备。无启动依赖。
**ethend** (`:9090`) — 管理控制台 (Node.js Express):服务启停、日志监控、性能分析。端口直接暴露到宿主机(不经过 Caddy)。无启动依赖。
### 基础设施层
**PostgreSQL** (`:5432`) — `pgvector/pgvector:pg16` 镜像,存储用户、会话、消息、记忆、IoT 设备状态。健康检查 `pg_isready` 每 10s 一次,5 次失败才判定不健康。
**Redis** (`:6379`) — `redis:7-alpine`WebSocket 会话缓存、JWT 黑名单、限流计数器。健康检查 `redis-cli ping`
**Qdrant** (`:6333-6334`) — 向量数据库,记忆语义检索。无健康检查(非启动依赖)。
**MinIO** (`:9000-9001`) — S3 兼容对象存储,存放用户上传的图片和文件。
---
## 启动序列
```
Phase 1 (并行) Phase 2 (并行) Phase 3 (并行)
┌──────────┐ ┌──────────────┐ ┌──────────────┐
│ postgres │─健康──▶ │ gateway │ │ voice-svc │
│ redis │─健康──▶ │ ai-core │ │ iot-debug │
│ qdrant │ │ memory-svc │ │ ethend │
│ minio │ │ caddy │ │ │
│ searxng │ └──────────────┘ └──────────────┘
└──────────┘ 等 PG/Redis 健康 无依赖,立即启动
总是启动
```
- **Phase 1** — 基础设施 + 搜索引擎,无依赖,总是最先启动
- **Phase 2** — gateway / ai-core / memory-service 等待 PostgreSQL + Redis 健康检查通过;caddy 等待 gateway 容器启动
- **Phase 3** — voice-service / iot-debug-service / ethend 零依赖,立即启动
---
## 运行时状态
```bash
$ docker compose ps
NAME STATUS PORTS
cyrene_caddy Up 0.0.0.0:80->80, 0.0.0.0:443->443
cyrene_gateway Up (healthy) 8080/tcp
cyrene_ai_core Up 8081/tcp
cyrene_memory_service Up 8091/tcp
cyrene_voice_service Up 8093/tcp
cyrene_iot_debug_service Up 8083/tcp
cyrene_ethend Up 0.0.0.0:9090->9090/tcp
cyrene_searxng Up 8080/tcp
cyrene_postgres Up (healthy) 5432/tcp
cyrene_redis Up (healthy) 6379/tcp
cyrene_qdrant Up 6333-6334/tcp
cyrene_minio Up 9000-9001/tcp
```
**对外可达**
| 地址 | 经过 |
|------|------|
| `http://<IP>/api/v1/chat` | Caddy → Gateway → AI-Core |
| `ws://<IP>/ws` | Caddy → Gateway WebSocket |
| `http://<IP>:9090` | 直连 ethend |
**数据持久化** — 5 个 Docker 卷(`docker compose down` 不会删除,需加 `-v` 才清空):
| 卷 | 内容 |
|----|------|
| `pg_data` | 所有业务数据(用户、会话、消息、记忆) |
| `redis_data` | 会话缓存 |
| `qdrant_data` | 向量索引 |
| `minio_data` | 上传文件 |
| `caddy_data` | TLS 证书 |
---
## 环境变量
所有变量在 `.env` 中配置,完整模板见 [.env.example](../../.env.example)。
### 必填(服务启动 panic 若缺失)
| 变量 | 说明 |
|------|------|
| `LLM_API_URL` | LLM API 地址 |
| `LLM_API_KEY` | LLM API 密钥 |
| `ADMIN_PASSWORD` | 管理员密码 |
| `JWT_SECRET` | JWT 签名密钥 |
| `INTERNAL_SERVICE_TOKEN` | 服务间通信认证 Token |
| `POSTGRES_PASSWORD` | 数据库密码 |
| `MINIO_SECRET_KEY` | MinIO 密钥 |
### 推荐配置
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `LLM_MODEL` | `gpt-4o` | 主模型 |
| `LLM_FALLBACK_MODEL` | `gpt-4o-mini` | 回退模型 |
| `ADMIN_USERNAME` | `admin` | 管理员用户名 |
| `ADMIN_NICKNAME` | `管理员` | AI 对管理员的称呼 |
| `REGISTRATION_ENABLED` | `false` | 开放注册(生产建议关闭) |
| `ALLOWED_ORIGINS` | `http://localhost:5173,...` | CORS 白名单 |
| `ENABLE_BACKGROUND_THINKING` | `true` | 后台自主思考 |
| `ACME_EMAIL` | — | Let's Encrypt 证书邮箱 |
## 域名与 HTTPS
`.env` 中设置 `DOMAIN``ACME_EMAIL`
```bash
# 无域名(仅 HTTP
DOMAIN=
# 有域名(自动 HTTPS
DOMAIN=your-domain.com
ACME_EMAIL=admin@your-domain.com
```
Caddy 在 `DOMAIN` 有值时自动从 Let's Encrypt 申请 TLS 证书,无需额外配置。
## 常用命令
```bash
# 重新构建并启动单个服务
docker compose up -d --build gateway
# 查看特定服务日志
docker compose logs -f ai-core
# 停止所有服务
docker compose down
# 停止并删除数据卷(危险)
docker compose down -v
```