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

6.3 KiB
Raw Blame History

Docker + Prefect 使用说明

当前方案是:

  • 使用 prefect.yaml 管理 deployment
  • 使用 Docker 容器运行 Prefect worker
  • 由 Prefect Server 统一调度

当前只有一条调度:

  • 12:00 执行物流未发货数据同步,并写入飞书多维表格

1. 创建 Docker 镜像

在项目目录执行:

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

2. 启动 Docker 容器

推荐使用 Compose。

项目里的 docker-compose.yaml 已经配置了:

  • .env
  • PREFECT_API_URL
  • FEISHU_CHAT_ID
  • host.docker.internal
  • uv_cache 持久化卷
  • CPU / 内存资源限制

启动:

cd /Users/idss/YXT_Project/logistics-service
docker compose up -d --build

停止:

docker compose down

查看运行状态:

docker ps

当前容器名是:

prefect-logistics-worker

3. 容器启动后会做什么

容器启动后:

  1. 加载 .env
  2. 创建 /app/logs
  3. 启动 supervisord
  4. 再由 supervisord.conf 启动:
prefect worker start --pool "logistics-service-pool" --type process

也就是说,这个容器的职责不是直接跑 flow,而是作为 Prefect worker 等待调度。

4. 注册 Prefect 调度

调度定义在 prefect.yaml。

当前 work pool 是:

logistics-service-pool

注册 deployment 的方式:

方式 A:在本机或服务器上直接执行

前提是当前环境里有 prefect CLI,并且能访问 PREFECT_API_URL:

cd /Users/idss/YXT_Project/logistics-service
prefect deploy --all

方式 B:在容器里执行

如果宿主机没有 prefect 命令,可以直接在容器里执行:

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 注册到 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 里的 flow
  5. flow 调用 import_logistics_to_feishu_bitable.py:
    • 查询 PostgreSQL
    • 删除多维表旧记录
    • 写入新记录
  6. 同步完成或失败后,使用 FEISHU_APP_ID、FEISHU_APP_SECRET 和 FEISHU_CHAT_ID 推送结果到飞书群

6. 单次手动执行

手动跑一次同步:

python /Users/idss/YXT_Project/logistics-service/prefect_logistics_scheduler.py --mode sync

如果要在 Docker 里手动执行:

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 容器日志:

docker logs -f prefect-logistics-worker

或者:

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

查看方式:

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。
可改为在容器里执行:

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 已经加了:

extra_hosts:
  - "host.docker.internal:host-gateway"

所以更推荐把 .env 里的 PREFECT_API_URL 配成类似:

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 容器
cd /Users/idss/YXT_Project/logistics-service
docker compose up -d --build
  1. 在能连到 PREFECT_API_URL 的环境里注册 deployment
docker exec -it prefect-logistics-worker sh -lc 'cd /app && prefect deploy --all'
  1. 到 Prefect UI 检查:
    • deployment 是否已注册
    • work pool 是否是 logistics-service-pool
    • schedule 是否是每天 12:00