Day 02 / 共 20 天 · 第 1 周 环境与骨架
Docker 跑起来
今天的目标不是读源码,是把 Coze Loop 真正跑起来、点开界面看一眼。有了直观的产品体感,后面读代码才有"这段代码在为哪个按钮服务"的方向感。
📍 你在整门课的位置 · 第 1 周 环境与骨架(共 4 周 · 20 天)
D1 项目全景→
D2 Docker 跑起来→
D3 进程启动→
D4 HTTP 网关→
D5 Handler 桥接
L01
为什么先跑起来再读代码
🤔 痛点:一上来就啃 DDD 四层,容易学得很虚
如果你还没见过 Coze Loop 的界面,那"Prompt 模块""评测模块"这些词就只是抽象名词。先把服务跑起来,点几下"新建 Prompt",你脑子里才会真正长出"哦这个按钮点下去,大概经过 handler → application → domain → infra 这条链路"的具体画面。
💡 本质:用 Docker Compose 一次性拉起"一整个小型分布式系统"
Coze Loop 不是一个单体小程序,它依赖 MySQL、Redis、ClickHouse、MinIO(对象存储)、RocketMQ(消息队列)五个基础设施,外加应用本身和一个 Nginx。手动一个个装非常麻烦,官方把它们全部打包进 release/deployment/docker-compose/ 下的几个 compose 文件,一条命令拉起全部。
🍼 类比:开一家餐厅前先把水电煤气接通
在正式营业(读代码研究菜谱)之前,先把厨房的水(MySQL 存数据)、电(Redis 缓存/锁)、燃气(RocketMQ 消息)、冷库(MinIO 存文件)都接通,再去看后厨怎么炒菜才有意义。
L02
docker-compose 目录结构
部署相关的一切都在 release/deployment/docker-compose/ 下:
release/deployment/docker-compose/
├── .env # 环境变量:镜像版本、端口、各种密码
├── docker-compose.yml # 基础服务定义(app + 5 件基础设施 + nginx)
├── docker-compose-dev.yml # 开发模式覆盖(本地构建镜像)
├── docker-compose-debug.yml # 调试模式覆盖(含 Delve 远程调试端口)
├── conf/
│ └── model_config.yaml # LLM 模型配置(今天要改的唯一文件)
└── bootstrap/ # 各服务的初始化脚本(entrypoint/healthcheck)
三个 compose 文件是"叠加"关系:
docker-compose.yml 是基础骨架,-dev.yml/-debug.yml 是在它之上叠加覆盖(Docker Compose 的多文件合并机制)。日常体验用基础模式就够,想边改代码边热更新用 dev 模式,想用 IDE 远程调试用 debug 模式。L03
一键起服务:make compose-up
根目录 Makefile 把一长串 docker compose 参数封装成了好记的命令:
| 命令 | 说明 |
|---|---|
make compose-up | 启动基础服务(默认开发模式,用官方发布镜像) |
make compose-down | 停止基础服务 |
make compose-down-v | 停止并删除 volumes(数据库数据也会清空,慎用) |
make compose-up-dev | 启动开发模式(本地构建应用镜像,改代码后重启生效) |
make compose-up-debug | 启动调试模式(含 Delve 远程调试端口 40000) |
make compose-restart-<svc> | 只重启某个基础服务,比如 make compose-restart-mysql |
💡 本质:docker-compose.yml 里的 profiles 决定"这次启动带哪些服务"
打开 docker-compose.yml 会看到每个服务都有
profiles: [ "app", "redis", ... ] 这样的字段——Docker Compose 的 profile 机制允许你按需选择性启动一部分服务,而不是每次都全量拉起。app 服务还用 depends_on + condition: service_healthy 声明了"必须等 MySQL/ClickHouse/MinIO/RocketMQ 都健康检查通过才启动"——这是编排一个有依赖顺序的分布式系统的标准写法。L04
配置模型:model_config.yaml
🤔 痛点:服务起来了,但一调用模型就报错
Coze Loop 本身不自带模型,你得告诉它去哪家调、用哪个 Key。这一步几乎是唯一"必须手动改"的配置。
编辑 release/deployment/docker-compose/conf/model_config.yaml,把 api_key 和 model 换成你自己的(以火山方舟为例):
models:
- id: 1
name: "doubao"
frame: "eino" # 统一走 Eino 框架调用(Day 10 细讲)
protocol: "ark" # 火山方舟协议,其它还支持 openai/claude/gemini/qwen 等
protocol_config:
api_key: "你的火山方舟 API Key"
model: "你的 Endpoint ID"
param_config:
param_schemas:
- name: "temperature"
default_val: "0.7"
- name: "max_tokens"
default_val: "2048"
为什么字段里有个
frame: "eino"? 这暗示了模型接入层是可插拔的——理论上除了 Eino,未来也可能接别的调用框架。目前 Coze Loop 统一用 Eino(字节 CloudWeGo 的 Go LLM 框架)做这层适配,protocol 字段则决定 Eino 内部用哪个厂商的 SDK builder(Day 10 会看到 ark/openai/claude/gemini/... 各自的 builder 函数)。⚠️ 坑:改完配置文件不会自动生效
model_config.yaml 是在容器启动时被挂载读取的,改完文件后要重启 app 容器(make compose-restart-app 或重新 compose-up)才会生效,单纯保存文件不会热更新。L05
五件基础设施速览
docker-compose.yml 里定义的服务,每一个都对应后面某天要读的 backend/infra/ 子目录:
🗄️
MySQL
主存储:Prompt/评测/用户等结构化数据
⚡
Redis
缓存 + 分布式锁 + ID 生成器
📊
ClickHouse
Trace/Span 分析型查询(观测模块专用)
📦
MinIO
S3 兼容对象存储:文件、大字段落盘
📨
RocketMQ
异步消息:Trace 摄入、任务调度解耦
🌐
Nginx
反代 + 挂载静态资源,对外统一入口
🍼 对照记忆
MySQL 是"档案室"(结构化数据永久存档),Redis 是"便签墙"(临时高频读写),ClickHouse 是"监控录像分析室"(海量 Trace 做统计分析),MinIO 是"仓库"(存大文件),RocketMQ 是"传送带"(把活儿从一个环节送到下一个环节而不用互相等待)。
L06
访问与排障
全部健康检查通过后,浏览器打开:
🌐 http://localhost:8082
如果打不开或报错,docs/guidance/deployment-guide.md 是排障第一站,几个常用排查命令:
# 看所有容器状态,重点看 STATUS 是否 healthy
docker compose -f release/deployment/docker-compose/docker-compose.yml ps
# 看应用日志(最常用)
docker logs -f coze-loop-app
# 看某个基础设施日志,比如 MySQL 初始化失败
docker logs -f coze-loop-mysql-init
⚠️ 坑:app 容器一直卡在 unhealthy
看 docker-compose.yml 里
app 服务的 depends_on:它要等 mysql/clickhouse/minio/rocketmq-namesrv/rocketmq-broker 都 service_healthy,还要等三个 *-init 一次性任务 service_completed_successfully。任何一个基础设施没起来,app 都会一直等。先用上面的 ps 命令定位是哪个服务没通过健康检查,再看它自己的日志。L07
今日小结 + 动手
🧠 今天你应该能回答
- Coze Loop 依赖哪几个基础设施?(MySQL/Redis/ClickHouse/MinIO/RocketMQ)
- 一键启动用什么命令?(
make compose-up,本质是包了一层的docker compose) - 模型怎么接进去?(改
conf/model_config.yaml的api_key/model,重启 app 容器生效) - 访问地址是什么?(
http://localhost:8082)
✋ 动手 5 分钟(即使暂时不方便本地跑,也把命令记下来)
# 1. 克隆代码
git clone https://github.com/coze-dev/coze-loop.git && cd coze-loop
# 2. 配置模型(编辑 api_key / model 字段)
vim release/deployment/docker-compose/conf/model_config.yaml
# 3. 一键启动
make compose-up
# 4. 查看状态 & 打开浏览器
docker compose -f release/deployment/docker-compose/docker-compose.yml ps
open http://localhost:8082
# 5. 想边改代码边验证效果,改用开发模式
make compose-up-dev
明天预告 · Day 03:界面能打开了,接下来我们扒开
backend/cmd/main.go——一个 Go 二进制文件启动的时候,到底按什么顺序把 MySQL/Redis/ClickHouse 连上、把六大模块的 handler 组装起来、最后监听 HTTP 端口。