Cog CLI 实战手册:从 cog init 到 cog push 的模型容器化拆解
【免费下载链接】cogContainers for machine learning项目地址: https://gitcode.com/GitHub_Trending/co/cog
一条cog run -i image=@cat.jpg,就能把当前目录的模型代码构建成 Docker 镜像、拉起容器、跑完一次推理,再把结果图写进磁盘。这是 Cog CLI 的日常——一个用 Go 编写的"机器学习容器"命令行工具,覆盖项目起步、本地调试、镜像构建、注册表发布的所有环节,而你的 Python 模型代码全程不会在宿主机上执行。
它解决什么问题
Cog CLI 站在"一个 Python 模型项目"和"一张标准 OCI 镜像"之间:你负责写cog.yaml和run.py,剩下的事——装依赖、生成 OpenAPI schema、吐 Dockerfile、起运行时、暴露 HTTP 接口——全部外包给它。
本文分两个视角展开:
- 用户视角:按"你想做什么"挑命令,速查表加参数与坑点,目标是照着敲就能跑;
- 工程视角:以
cog run为样本拆调用链,讲几个设计决策,最后给源码地图和集成测试的对应关系。
用户视角:按场景选命令
速查:你的目标决定命令
| 你的目标 | 命令 | 一句话说明 |
|---|---|---|
| 起一个新模型项目 | cog init | 生成cog.yaml与run.py骨架 |
| 跑一次推理看结果 | cog run | 需要时先构建,再启容器流式输出 |
| 在容器里执行任意命令 | cog exec | 验 CUDA、开 Jupyter、跑训练脚本 |
| 本地 HTTP 联调 | cog serve | 暴露/predictions等端点 |
| 产出独立 Docker 镜像 | cog build | 可打 tag、可分离权重层 |
| 推送到注册表 | cog push | 任意 OCI 注册表;r8.im 需先 login |
| 注册表认证 | cog login | r8.im 走 token,其他走用户名/密码 |
起步:cog init 生成项目骨架
场景:空目录,准备写一个新模型。
cog init模板通过 Go 的embed.FS打包在二进制里,离线也能工作。生成物是cog.yaml(Python 版本、GPU 开关、requirements.txt路径、run 入口等合理默认值)和run.py(一个继承BaseRunner的类,setup()一次性加载模型,run()处理单次输入,参数用Input(description=..., ge=0, le=10, default=1.5)这种约束写法),模板里有的requirements.txt会一并生成。
两个细节值得知道:
- 文件已存在时只打印
Skipped existing ...然后跳过,绝不覆盖你的代码; AGENTS.md会先从 Replicate 文档站拉最新版,失败才回退到内嵌模板。
试跑:cog run 的输入与输出
场景:模型写完了,想在终端验证一次输出。
cog run -i prompt="A photo of a cat" -i steps=50 cog run -i image=@photo.jpg -o out.png echo '{"prompt": "a cat"}' | cog run --json @-带源码的本地跑法顺序是:静态生成 schema → 解析并校验输入 → 构建镜像 → 启动容器 → 对/predictions发请求 → 输出按类型呈现。若你传了一个已构建的镜像名,则跳过构建,直接拉取并运行,优先用镜像上的 schema label 做预校验。
-i的值加@前缀表示本地文件:CLI 读文件、按扩展名推 MIME、base64 成 data URL 传给容器;写 URL 字符串则按 URL 处理。输出端:字符串原样打印,Path/list[Path]落盘(多个时自动命名name.0.ext、name.1.ext),整型/浮点/布尔打原始值,列表与对象走缩进 JSON;预测失败进程以非零码退出。
| 参数 | 说明 |
|---|---|
-i, --input name=value | 可重复;@前缀读本地文件 |
-o, --output path | 输出落盘路径,缺省按类型呈现 |
-e, --env name=value | 注入容器环境变量 |
--json @file / @- | 整包 JSON 传输入,与-i互斥 |
--use-replicate-token | 把宿主机REPLICATE_API_TOKEN传入模型上下文 |
--setup-timeout | 容器 setup 超时秒数,默认 300 |
--gpus | 与docker run --gpus同格式 |
-f, --file | 配置文件路径,默认cog.yaml |
| 构建系标志 | --use-cuda-base-image/--use-cog-base-image/--dockerfile/--progress,与cog build一致 |
调试:cog exec 进容器看现场
场景:怀疑某个依赖没装上,或想确认 CUDA 到底可不可用。
cog exec python -c "import torch; print(torch.cuda.is_available())" cog exec -p 8888 jupyter notebook cog exec -e HUGGING_FACE_HUB_TOKEN=abc123 python download.py它按cog.yaml构建临时镜像,把当前目录挂载为/src并设为工作目录,容器里随手就能碰你的文件。实现上用SetInterspersed(false)把第一个位置参数之后的所有内容原样交给容器命令,所以引号、连字符都不会被 CLI 吞掉。
坑点:-p支持8000、0.0.0.0:8000、[::1]:8000三种写法;构建路径跳过 schema 校验,比run更快。
本地联调:cog serve 起 HTTP 服务
场景:前端或上游服务要按 HTTP 协议调你的模型,想在本地先跑通生产同款接口。
cog serve curl http://localhost:8393/predictions -X POST \ -H 'Content-Type: application/json' \ -d '{"input": {"prompt": "a cat"}}'注意端口约定:容器内服务固定监听 5000,宿主机默认映射到 8393,所以访问地址是http://localhost:8393而不是 5000。跑起来之后,POST /predictions发预测、/openapi.json看规范、/health-check探活。
常用开关:-p改宿主机端口;--host 0.0.0.0允许外部访问(默认只绑 127.0.0.1);--upload-url指定文件输出的上传地址(Linux 上 CLI 会自动加host.docker.internal:host-gateway让容器够得着宿主机);--gpus直通;另有--playground可在旁边起一个操作界面。环境变量会注入LOG_FORMAT=console,日志是本地开发友好的可读格式。cog serve不解析任何预测输入——只构建、启动、保持运行。
出镜像:cog build 参数速查
场景:CI 要一份可流转的镜像产物,或者要把环境固化下来分发给别人。
cog build -t my-model:latest cog build --no-cache --separate-weights内部六步:解析cog.yaml(含 CUDA/cuDNN、PyTorch 兼容矩阵)→ 解析 CUDA 版本 → 用 tree-sitter 解析run.py类型注解、静态生成 OpenAPI schema → 生成 Dockerfile → 交给 BuildKit 构建 → 往镜像写 schema、config、pip freeze 等 label。
参数面:
-t, --tag:镜像标签。镜像名优先级:-t>cog.yaml的image字段 >model字段 > 按项目目录生成的默认名;--no-cache:禁用构建缓存;--separate-weights:权重拆到独立层,便于单独上传;--progress:auto(默认)/tty/plain/quiet,BUILDKIT_PROGRESS环境变量可覆盖默认;--secret id=foo,src=/path/to/file:构建期密钥;--openapi-schema:用文件里的 schema 替代静态生成;--use-cuda-base-image:auto(默认)/true/false,false 用纯 Python 基础镜像,体积小但非 torch 项目可能踩坑;--use-cog-base-image:默认开,用预构建 Cog 基础镜像加速冷启动;- 隐藏参数:
--dockerfile(自带 Dockerfile 替代生成)、--timestamp(重写层时间戳做可复现构建)、--strip(剥离共享库符号)、--precompile(预编译 Python 文件)、--skip-schema-validation。
一条硬规则:--use-cog-base-image、--use-cuda-base-image、--dockerfile三者互斥,同时设两个直接报错。
发布:cog login 与 cog push
场景:本地验证通过,把模型发出去。
cog login cog login --token-stdin < token.txt cog push r8.im/your-username/my-model cog push registry.example.com/you/model --separate-weightslogin按注册表主机查对应 provider:r8.im 走 token 认证(--token-stdin适配 CI 非交互场景),其他注册表提示输入用户名/密码,凭证存进 Docker 的 credential 系统;主机可用全局--registry或COG_REGISTRY_HOST覆盖。push先做参数预校验,把COG_MODEL/COG_MODEL_TAG与cog.yaml里model/image的冲突在秒级报出来,而不是构建数分钟后才炸;随后走与build相同的路径构建,resolver.Push()推送(含分离的权重层),最后由目标注册表的 provider 做收尾——比如打印 Replicate 的模型 URL。成功后终端会打印树状的 digest 固定引用(model/image/weight各行),可直接复制。
坑点:--separate-weights是 Replicate 专属能力;除此之外cog push接受任何 OCI 注册表地址。
藏在 help 后面的命令
cog debug:只生成 Dockerfile 到.cog/临时目录而不构建,专治构建问题排查;cog weights(实验性):import/pull/status三个子命令,把cog.yaml的权重源打包成 OCI 层、维护weights.lock;import 之后cog run能直接挂载权重,省去单独 pull;cog predict:cog run的弃用别名,调用会先看到一行弃用警告;cog train:同样标记弃用,向/trainings端点发请求;- 另有独立的
base-image二进制(cmd/base-image/),管理 Cog 基础镜像,不是cog的子命令。
工程视角:一条 cog run 的全链路
先回答一个反直觉的问题:镜像都还没构建,输入类型怎么就校验上了?因为 schema 不是从运行中的模型问出来的,而是静态分析出来的——pkg/schema/用 tree-sitter 解析 Python 注解直接产出 OpenAPI 规范。所以校验可以发生在构建之前。
走已构建镜像的路径则不同:先 pull,若镜像带可用的 schema label 就提前校验输入;label 缺失时容器启动后通过predictor.GetSchema()回退到运行时 schema,再补做一轮校验。两条路径最终汇合到同一个Predict调用。
几个设计决策的来龙去脉
- 模型代码不碰宿主机。
run/serve/exec共享同一形态:model.NewSource加载配置 →resolver.Build()出镜像 →docker.Run()或predict.NewPredictor()起容器。CLI 只当编排者,setup()与run()全部发生在与cog.yaml声明严格一致的容器环境里(见 pkg/cli/predict.go 与 pkg/cli/serve.go)。 - 输入校验先于构建。静态 schema 在构建前生成、校验,并顺带写进构建选项;类型拼错在镜像开工前就报错,省掉数分钟构建时间(
generateLocalOpenAPISchema→prepareInputs的先后顺序在 pkg/cli/predict.go 中一目了然)。 - GPU 缺失不卡死。
--gpus未显式指定且模型需要 GPU 时以gpus=all启动;若 Docker 报缺设备驱动(ErrMissingDeviceDriver),自动去掉 GPU 参数重试,并提示Missing device driver, re-trying without GPU。serve与run两条路径都有这个回退。 - RUST_LOG 透传。容器内的 Rust 运行时(coglet)日志级别由
RUST_LOG控制,CLI 会把宿主机同名环境变量原样带进容器,调试不用两边来回切。
源码地图
入口 cmd/cog/cog.go 很薄:创建根命令、Execute(),错误统一交给console.Fatalf。根命令 pkg/cli/root.go 做两件事:批量挂载子命令(build / run / exec / serve / push / login / init / debug / doctor / playground / train / weights,外加隐藏的 predict);声明持久标志--debug、--no-color、--version与隐藏的--profile、--registry。PersistentPreRun钩子按--debug调日志级别、按--no-color写NO_COLOR环境变量,并触发版本更新检查;cobra.EnableTraverseRunHooks让子命令可以追加自己的钩子且按根→子顺序执行。
模块分工大致如下:
cmd/cog/ 入口 pkg/cli/ Cobra 命令层,一个文件一条命令 pkg/config/ cog.yaml 解析校验,CUDA / torch 兼容矩阵 pkg/schema/ 静态 OpenAPI 生成(tree-sitter 解析 Python) pkg/dockerfile/ Dockerfile 生成与基础镜像选择 pkg/image/ 构建编排 pkg/docker/ Docker / BuildKit 客户端 pkg/predict/ 与容器内运行时通信(predictor、输入转换) pkg/model/ OCI 工件模型,resolver 负责构建/拉取编排 pkg/provider/ 注册表行为抽象(Replicate 与通用 OCI) pkg/registry/ OCI 注册表客户端 pkg/weights/ 权重发现、lockfile、本地 store pkg/dotcog/ .cog/ 项目状态目录 pkg/errors/ 带错误码的 CodedError集成测试在盯什么
integration-tests/tests/ 下是 txtar 格式的端到端用例,几个名字和上文行为直接对应:
input_validation_before_build.txtar——输入在构建前就被类型校验拦下;union_input_cli.txtar——union 类型输入在 CLI 模式下的解析路径;predict_json_input.txtar——--json @-从 stdin 喂整包输入的链路;predict_output_file.txtar——-o的落盘与回退命名;pty_interactive.txtar——交互式终端透传(exec类场景);build_openapi_schema.txtar——构建时 schema 被打进镜像 label;doctor_predict_to_run_migration.txtar——cog doctor识别旧式predict写法并提示迁移到run。
场景速查
| 场景 | 命令 |
|---|---|
| 新写一个模型项目 | cog init |
| 验证单次输出 | cog run -i k=v |
| 检查 CUDA / 依赖 | cog exec python -c ... |
| 前端联调 | cog serve |
| CI 产出镜像 | cog build -t name:tag |
| 发布上线 | cog login && cog push r8.im/you/model |
CLI 的价值边界很清楚:它只负责编排,模型的一比特代码都在容器里执行。想继续往下钻,推荐按顺序读 architecture/02-schema.md、architecture/03-prediction-api.md 与 architecture/04-container-runtime.md,正好对应本文"静态 schema → HTTP 协议 → 容器内运行时"这条主线。
【免费下载链接】cogContainers for machine learning项目地址: https://gitcode.com/GitHub_Trending/co/cog
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考