Files
logistics-service/DOCKER_PREFECT_USAGE.md
2026-03-26 10:52:35 +08:00

270 lines
6.3 KiB
Markdown
Raw Permalink 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 + Prefect 使用说明
当前方案是:
- 使用 [prefect.yaml](/Users/idss/YXT_Project/logistics-service/prefect.yaml) 管理 deployment
- 使用 Docker 容器运行 Prefect worker
- 由 Prefect Server 统一调度
当前只有一条调度:
- `12:00` 执行物流未发货数据同步,并写入飞书多维表格
## 1. 创建 Docker 镜像
在项目目录执行:
```bash
cd /Users/idss/YXT_Project/logistics-service
docker build -t logistics-service-prefect:0.1.0 .
```
镜像构建特点:
- 基础镜像:`python:3.12-slim-bookworm`
- 使用 `uv` 安装依赖
- 使用清华 `apt` 和 `PyPI` 源
- 依赖来源:[pyproject.toml](/Users/idss/YXT_Project/logistics-service/pyproject.toml)
## 2. 启动 Docker 容器
推荐使用 Compose。
项目里的 [docker-compose.yaml](/Users/idss/YXT_Project/logistics-service/docker-compose.yaml) 已经配置了:
- `.env`
- `PREFECT_API_URL`
- `FEISHU_CHAT_ID`
- `host.docker.internal`
- `uv_cache` 持久化卷
- CPU / 内存资源限制
启动:
```bash
cd /Users/idss/YXT_Project/logistics-service
docker compose up -d --build
```
停止:
```bash
docker compose down
```
查看运行状态:
```bash
docker ps
```
当前容器名是:
```bash
prefect-logistics-worker
```
## 3. 容器启动后会做什么
容器启动后:
1. 加载 `.env`
2. 创建 `/app/logs`
3. 启动 `supervisord`
4. 再由 [supervisord.conf](/Users/idss/YXT_Project/logistics-service/supervisord.conf) 启动:
```bash
prefect worker start --pool "logistics-service-pool" --type process
```
也就是说,这个容器的职责不是直接跑 flow,而是作为 Prefect worker 等待调度。
## 4. 注册 Prefect 调度
调度定义在 [prefect.yaml](/Users/idss/YXT_Project/logistics-service/prefect.yaml)。
当前 work pool 是:
```bash
logistics-service-pool
```
注册 deployment 的方式:
### 方式 A:在本机或服务器上直接执行
前提是当前环境里有 `prefect` CLI,并且能访问 `PREFECT_API_URL`:
```bash
cd /Users/idss/YXT_Project/logistics-service
prefect deploy --all
```
### 方式 B:在容器里执行
如果宿主机没有 `prefect` 命令,可以直接在容器里执行:
```bash
docker exec -it prefect-logistics-worker sh -lc 'cd /app && prefect deploy --all'
```
注意:
- 这条命令要求容器里的 `PREFECT_API_URL` 可访问
- 如果你看到 `ConnectError`,通常是 `.env` 里的 `PREFECT_API_URL` 地址在容器里不可达
## 5. 自动执行是怎么发生的
完整流程如下:
1. `prefect deploy --all` 把 [prefect.yaml](/Users/idss/YXT_Project/logistics-service/prefect.yaml) 注册到 Prefect Server
2. Prefect Server 根据 cron 在每天 `12:00` 触发:
- `logistics-bitable-sync-daily`
3. `prefect-logistics-worker` 容器里的 worker 从 `logistics-service-pool` 拉取任务
4. worker 执行 [prefect_logistics_scheduler.py](/Users/idss/YXT_Project/logistics-service/prefect_logistics_scheduler.py) 里的 flow
5. flow 调用 [import_logistics_to_feishu_bitable.py](/Users/idss/YXT_Project/logistics-service/import_logistics_to_feishu_bitable.py):
- 查询 PostgreSQL
- 删除多维表旧记录
- 写入新记录
6. 同步完成或失败后,使用 `FEISHU_APP_ID`、`FEISHU_APP_SECRET` 和 `FEISHU_CHAT_ID` 推送结果到飞书群
## 6. 单次手动执行
手动跑一次同步:
```bash
python /Users/idss/YXT_Project/logistics-service/prefect_logistics_scheduler.py --mode sync
```
如果要在 Docker 里手动执行:
```bash
docker run --rm \
--env-file /Users/idss/YXT_Project/logistics-service/.env \
-e PREFECT_API_URL=http://host.docker.internal:4200/api \
--add-host host.docker.internal:host-gateway \
logistics-service-prefect:0.1.0 \
python prefect_logistics_scheduler.py --mode sync
```
## 7. Docker 中的日志
现在日志分成三层:
### 7.1 容器标准输出日志
查看 worker 容器日志:
```bash
docker logs -f prefect-logistics-worker
```
或者:
```bash
cd /Users/idss/YXT_Project/logistics-service
docker compose logs -f
```
这里通常能看到:
- worker 启动日志
- Prefect 调度执行日志
- Python 进程报错堆栈
### 7.2 容器内本地文件日志
worker 的 supervisor 日志会写到:
- `/app/logs/prefect_worker.out.log`
- `/app/logs/prefect_worker.err.log`
查看方式:
```bash
docker exec -it prefect-logistics-worker sh
tail -f /app/logs/prefect_worker.out.log
```
### 7.3 Prefect UI 日志
在 Prefect UI 的 `Logs` 面板里也能看到 flow / task 日志。
如果 UI 没看到新日志,通常说明:
- worker 还没重启到最新代码
- 或本次 run 还是旧 deployment / 旧镜像执行的
## 8. 常见问题
### 8.1 `prefect: command not found`
说明宿主机没有安装 Prefect CLI。
可改为在容器里执行:
```bash
docker exec -it prefect-logistics-worker sh -lc 'cd /app && prefect deploy --all'
```
### 8.2 `httpx.ConnectError: All connection attempts failed`
说明容器里访问不到 `PREFECT_API_URL`。
常见原因:
- `.env` 里的 `PREFECT_API_URL` 写成了 `localhost`
- 容器里访问不到宿主机 Prefect API
当前 compose 已经加了:
```yaml
extra_hosts:
- "host.docker.internal:host-gateway"
```
所以更推荐把 `.env` 里的 `PREFECT_API_URL` 配成类似:
```bash
PREFECT_API_URL=http://host.docker.internal:4200/api
```
### 8.3 飞书返回 `91403 Forbidden`
说明当前应用对目标多维表没有足够权限。
需要检查:
- 应用是否已添加到目标 Base
- 是否具备可编辑权限
- 是否允许新增记录 / 删除记录 / 新增字段
### 8.4 没有收到飞书群通知
需要检查:
- `.env` 中是否配置了 `FEISHU_CHAT_ID`
- 当前应用是否具备发送消息权限
- 该应用对应机器人是否已加入目标群
## 9. 最推荐的执行方式
如果你要的是“服务器上长期稳定自动执行”,建议按这个顺序:
1. 构建镜像
2. 准备 `.env`
3. 启动 worker 容器
```bash
cd /Users/idss/YXT_Project/logistics-service
docker compose up -d --build
```
4. 在能连到 `PREFECT_API_URL` 的环境里注册 deployment
```bash
docker exec -it prefect-logistics-worker sh -lc 'cd /app && prefect deploy --all'
```
5. 到 Prefect UI 检查:
- deployment 是否已注册
- work pool 是否是 `logistics-service-pool`
- schedule 是否是每天 `12:00`