FBO Shipment Service 运维 (4182, Docker)
ozon_fbo_shipment_service 是 Ozon 卖家 API 的 FBO 发货链路代理 (Draft/Supply Order/Cargoes/Label, 1:1 原子转发 + 2 个 flow 编排). 已容器化, 运行在 4182.
触发场景
- "起/停/重启 FBO 服务"
- "4182 服务健康检查"
- "看 FBO 容器日志"
- "FBO 服务挂了 / 没响应"
- "重建 FBO docker 镜像"
关键路径
- 源码 + Dockerfile + compose:
/Users/mac/Documents/ozns/github/ozon_fbo_shipment_service/ - docker CLI 不在 PATH, 路径是
/Applications/Docker.app/Contents/Resources/bin/docker - 容器名:
ozon-fbo-shipment(单容器, 没有网络依赖) - 端口: 宿主 4182 → 容器 4182
- 卷:
./labels:/app/labels(bind mount, 箱唛 PDF 落这里)
常用命令
总是先 export PATH, 再 docker compose:
export PATH=/Applications/Docker.app/Contents/Resources/bin:$PATH
cd /Users/mac/Documents/ozns/github/ozon_fbo_shipment_service
健康检查 (首选 — 先做这个再决定要不要重启)
docker ps --filter name=ozon-fbo-shipment --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
curl -s http://localhost:4182/health # 4182 有 /health
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:4181/docs # 4181 没 /health 用 /docs (200=活)
返回 {"ok": true, "accounts": [...]} = 正常.
注: rtk 代理会过滤 JSON, 用 rtk proxy curl ... 拿真实响应而不是 schema view.
启动 (首次 / 停机后)
docker compose up -d
重启 (代码没改, 只是卡了)
docker compose restart
代码改了 — 重建 + 重启
docker compose up -d --build
停服务
docker compose down
看日志
docker compose logs -f --tail 200 # 跟 (Ctrl-C 退出)
docker compose logs --since 10m # 最近 10 分钟
docker compose logs | grep -i error | tail -20
进容器调试
docker exec -it ozon-fbo-shipment bash
# 容器内: python3 -c "from ozon_fbo_shipment_service.app import app; print(len(app.routes))"
冲突排查
端口 4182 被宿主机 uvicorn 占用
常见: 之前手启的 python3 -m uvicorn ozon_fbo_shipment_service.app:app --port 4182 还活着, compose 会起不来.
lsof -iTCP:4182 -sTCP:LISTEN
# 有 Python <PID> → 先 kill
kill <PID>
docker compose up -d
镜像构建慢 / 失败
docker compose build --no-cache 2>&1 | tail -40 # 看完整报错
docker system df # 看磁盘占用
docker system prune -f # 清悬空镜像 (慎用)
.env 凭据问题
- 路径:
/Users/mac/Documents/ozns/github/ozon_fbo_shipment_service/.env OZON_ACCOUNTS_JSON={"丝绸生活":{"client_id":"...","api_key":"..."},...}一行 JSON- 改后:
docker compose restart(env_file 只在启动时读)
服务返回 Ozon 403 Api-key is deactivated
.env 里该账号 api_key 失效. 去 seller.ozon.ru 重生 + 改 .env + docker compose restart.
限流碰太紧 (timeslot/info 持续 429)
clients/rate_limits.py /v2/draft/timeslot/info 已收到 (1, 15) (2026-04-25 收紧). 多 cluster fallback 阶段内部循环时仍会 429, 再收紧到 (1, 30) 但会拉慢 retry. 看 feedback_429_masks_404_matrix.md 决策点.
docker cp 热修 (Docker Hub 挂时)
镜像 build 跑不了, 用 docker cp 推文件进运行容器临时跑:
docker cp clients/rate_limits.py ozon-fbo-shipment:/app/ozon_fbo_shipment_service/clients/
docker compose restart # 重启 reload module
临时, 下次 docker compose up -d --build 会丢. 网络恢复后必须 build 把改动固化进镜像 (feedback_docker_cp_hot_patch.md).
已剥离的能力 (2026-04-24 定稿)
/internal/seller/* (seller.ozon.ru BFF) 已去掉: 原本依赖 ozon-cookie-proxy:5100 + curl_cffi + 住宅代理. 用户定稿 "接口可以去掉ozon-cookie-proxy,这个没什么用". 公共 API (multi-cluster 链路) 已打通, BFF 旁路不再需要.
如果以后要恢复, 3 个改动:
app.py加from .routers import ... internal ...+app.include_router(internal.router)clients/__init__.py加from .seller_ui_client import SellerUIClient, SellerUIErrorrouters/_deps.py加seller_ui_client()依赖requirements.txt加curl_cffi>=0.7.0docker-compose.yml加extra_hosts: - "host.docker.internal:host-gateway"+OZON_COOKIE_PROXY_URL=http://host.docker.internal:5100
端点速查 (27 条)
# 拿完整列表
python3 -c "import urllib.request,json; d=json.load(urllib.request.urlopen('http://localhost:4182/openapi.json')); print('\n'.join(sorted(d['paths'])))"
核心:
POST /cluster/list— 集群列表POST /warehouse/fbo/list— 仓库搜索 (search 至少 4 字符)POST /draft/crossdock/create//draft/direct/create//draft/multi-cluster/createPOST /draft/create/info(v2, body{draft_id})POST /draft/timeslot/info(v2, supply_type=字符串)POST /draft/supply/create(v2) +/draft/supply/create/statusPOST /supply-order/get(v3) //supply-order/bundlePOST /cargoes/create+/cargoes/create/info(v2)POST /cargoes-label/create+/cargoes-label/getGET /cargoes-label/file/{guid}/save?supply_id=X— 下载 PDFPOST /flow/create-supply/POST /flow/upload-cargoes— 一把梭
交互文档: http://localhost:4182/docs
多账号调用
中文账号 header 必须 URL-encode:
ACCOUNT_URL=$(python3 -c "import urllib.parse; print(urllib.parse.quote('丝绸生活'))")
curl -X POST http://localhost:4182/cluster/list \
-H "Content-Type: application/json" \
-H "X-Ozon-Account: $ACCOUNT_URL" \
-d '{"cluster_type":"CLUSTER_TYPE_OZON"}'
账号列表: 丝绸生活 (默认), 个人之路, 个人之路_old (见 /health).
相关 skill / memory
/fbo-plan— 跑多集群发货 SOP 脚本/fbo-retry— 查/重试未发/fbo-fill-boxes— 填装箱 + 箱唛 PDF/fbo-status— 台账查询- memory
reference_fbo_shipment_service.md— 27 端点契约 - memory
feedback_fbo_service_docker_prereqs.md— 容器化决策与 Dockerfile 细节 - memory
reference_services_ports.md— 4180/4181/4182 全栈