ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Prefect 镜像构建的 BuildKit 支持:基于 python-on-whales 的 buildx 后端接入指南

Prefect 镜像构建的 BuildKit 支持:基于 python-on-whales 的 buildx 后端接入指南 Prefect 镜像构建的 BuildKit 支持基于 python-on-whales 的 buildx 后端接入指南【免费下载链接】prefectPrefect is a workflow orchestration framework for building resilient data pipelines in Python.项目地址: https://gitcode.com/GitHub_Trending/pr/prefect本篇指南介绍 Prefect 工作流编排框架中 Docker 镜像构建的 BuildKit 能力扩展通过引入python-on-whales作为可选的 buildx 构建后端让用户能够使用 build secrets、SSH 转发、多平台构建、--mount语法等现代 BuildKit 特性而默认的 docker-py 构建路径保持不变。读完本文你将掌握在 SDKDockerImage与prefect.yaml部署步骤两条构建路径上切换build_backendbuildx的完整用法、底层实现原理与测试验证方法。为什么需要第二个构建后端docker-py 的能力边界Prefect 长期以来使用 docker-py 完成所有镜像构建工作。随着 Docker 生态演进这条路径暴露出几个结构性限制依据设计文档 plans/completed/2026-03-25-buildkit-support.md 的 Background 部分docker-py 没有 BuildKit 支持。docker-py 的构建接口基于 Docker 的 legacy builder API对 BuildKit 的--mount、secret、SSH 等特性无能为力相关 issue 已搁置多年。Docker 的 legacy builder 自 v23.0 起被弃用。使用--mount语法例如缓存挂载RUN --mounttypecache的 Dockerfile 通过 docker-py 构建会直接失败。构建密钥无法安全传递。docker-py 路径下用户只能使用 build args 传入敏感信息而 build args 会明文暴露在镜像历史image history中存在安全隐患。python-on-whales 是可行的替代方案。它包装 Docker CLI 二进制通过类型化的 Python API 提供完整的 BuildKit/buildx 支持维护活跃并被 Apache Airflow 等项目采用。代码库已有 CLI 构建先例。prefect dev build-image早已通过 subprocess 调用 Docker CLI 完成构建说明在代码库中引入基于 CLI 的构建路径是合理的演进方向。方案还明确划定了非目标Non-Goals帮助读者理解改动边界不替换 docker-py它仍是默认后端不改变DockerWorker中容器 run/create/pull 的行为只影响 build 与 push不支持 Podman 或其他容器运行时尽管 python-on-whales 本身支持它们。架构总览两条路径 × 两个后端构建存在两条既有入口两者原先都经由 docker-py路径入口构建链路SDKflow.deploy()→DockerImage.build()dockerutils.build_image()→client.api.build()YAML stepsprefect deploy→build_docker_image()client.api.build()直接调用方案为两条路径各增加一条并行的 buildx 通道核心分发逻辑如下DockerImage(namemyimage, build_backendbuildx, platforms[linux/amd64]) │ ├── build_backenddocker-py (default) ──→ dockerutils.build_image() ──→ docker-py │ └── build_backendbuildx ──→ buildx.build_image() ──→ python-on-whales ──→ docker CLI从当前仓库的源码结构看该设计已完整落地新模块按计划实现但最终位置是 src/prefect/_internal/buildx.py核心实现并在 src/prefect/docker/_buildx.py 保留了兼容垫片向后兼容旧版集成包SDK 侧的分发实现在 src/prefect/docker/docker_image.pyYAML steps 侧的分发实现在 src/integrations/prefect-docker/prefect_docker/deployments/steps.py。安装与依赖策略可选的 buildx extrapython-on-whales被设计为可选依赖不影响默认路径的轻量安装主包在 pyproject.toml 中声明了buildxextrabuildx [python-on-whales0.81]注意落地实现与计划的一个差异在 src/integrations/prefect-docker/pyproject.toml 中python-on-whales0.81被直接写入了必选dependencies计划原打算在 prefect-docker 中也做成 optional extra。安装方式二选一# 方式一安装 Prefect 主包的 buildx extra pip install prefect[buildx] # 方式二安装 prefect-docker 集成已内置 python-on-whales pip install prefect-docker运行时导入守卫当用户设置build_backendbuildx但未安装 python-on-whales 时src/prefect/docker/docker_image.py 中的_ensure_buildx_extra()会立即抛出带安装指引的ImportErrorThe python-on-whales package is required for the buildx backend but is not installed. Install it with: pip install prefect[buildx]该检查在DockerImage.__init__中同步触发src/prefect/docker/docker_image.py让配置错误尽早暴露而不是等到构建执行阶段。在 SDK 中使用DockerImage(build_backendbuildx)DockerImage新增了build_backend参数src/prefect/docker/docker_image.pydef __init__( self, name: str, tag: Optional[str] None, dockerfile: str auto, stream_progress_to: Optional[TextIO] sys.stdout, build_backend: Literal[docker-py, buildx] docker-py, **build_kwargs: Any, ):关键语义build_backend仅接受docker-py与buildx两个取值传入其他值会抛出ValueError: Invalid build_backend ... Must be docker-py or buildxname、tag的解析沿用既有规则若镜像名不含命名空间registry URL 或 user/org 名会回退到PREFECT_DEFAULT_DOCKER_BUILD_NAMESPACE设置未显式提供tag时使用 UTC 时间戳经slugify生成**build_kwargs的透传语义随后端改变在DockerImagedocstring 中有明确说明docker-py→ 透传给 docker-py 的client.api.build()buildx→ 透传给python_on_whales.docker.buildx.build()可包含secrets、ssh、cache_from、cache_to、platforms、push等 buildx 原生参数。典型用法示例——构建并推送一个带构建密钥的 amd64 镜像from prefect.docker.docker_image import DockerImage image DockerImage( namemyregistry/my-image, taglatest, dockerfileDockerfile, build_backendbuildx, secrets[idpypi,src~/.pypirc], # BuildKit 构建密钥不会进入镜像历史 sshdefault, # SSH 转发如私有依赖克隆 cache_from[typeregistry,refmyregistry/my-image:cache], cache_to[typeinline], ) # 构建默认 dockerfileauto 时会自动生成并清理临时 Dockerfile image.build()构建推送一体化优化当build_backendbuildx时build()接受pushTrue的 kwarg将--push传递给 buildx让构建与推送在单一步骤内完成src/prefect/docker/docker_image.py。这是多平台构建的唯一可行方式见下节约束对单平台构建也更高效。当build()以pushTrue执行后内部会置位_pushed_during_build随后的push()调用自动成为 no-opsrc/prefect/docker/docker_image.py避免重复推送。image DockerImage( namemyregistry/my-image, build_backendbuildx, platforms[linux/amd64, linux/arm64], pushTrue, # 构建即推送multi-platform manifest list 直达 registry ) image.build() # 完成后 push() 无需也不应再调用在 prefect.yaml 部署步骤中使用prefect-docker集成的 build_docker_image 步骤 同样新增了build_backend参数默认docker-py非法取值同样抛出ValueErrorpush_docker_image步骤也同步支持build_backend当为buildx时改用buildx_push_image()。单平台构建 构建密钥build: - prefect_docker.deployments.steps.build_docker_image: requires: prefect-docker image_name: repo-name/image-name tag: dev build_backend: buildx secrets: - idpypi,src~/.pypirc cache_from: - typeregistry,refrepo-name/image-name:cache push: - prefect_docker.deployments.steps.push_docker_image: requires: prefect-docker image_name: {{ build-image.image_name }} tag: {{ build-image.tag }} build_backend: buildx多平台构建必须配合push: truebuild: - prefect_docker.deployments.steps.build_docker_image: requires: prefect-docker image_name: repo-name/image-name tag: v1.0.0 dockerfile: Dockerfile build_backend: buildx platforms: - linux/amd64 - linux/arm64 push: true在 buildx 分支中构建上下文从pathkwarg 弹出并默认为当前工作目录push、pull等参数被显式取出再连同additional_tags生成的extra_tags一起交给buildx_build_image()src/integrations/prefect-docker/prefect_docker/deployments/steps.py。底层实现剖析buildx_build_image 与 buildx_push_image核心模块 src/prefect/_internal/buildx.py 封装了所有 python-on-whales 交互。buildx_build_image函数签名src/prefect/_internal/buildx.pydef buildx_build_image( context: Path, dockerfile: str Dockerfile, tag: Optional[str] None, extra_tags: Optional[list[str]] None, pull: bool False, platform: Optional[str] None, stream_progress_to: Optional[TextIO] None, push: bool False, **kwargs: Any, ) - str:实现要点与 docker-py 路径严格对齐的工程细节上下文校验context必填且必须存在否则抛出ValueError多平台约束当platforms超过一个条目且pushFalse时抛出明确的ValueError——buildx 无法把多平台构建结果加载进本地 daemon结果只能以 manifest list 形式进入 registrysrc/prefect/_internal/buildx.py标签合并Prefect 的IMAGE_LABELS{io.prefect.version: prefect.__version__}定义于 src/prefect/utilities/dockerutils.py通过labels参数同样作用于 buildx 构建用户自定义标签会与之合并保证 buildx 产物与 docker-py 产物一致可溯源src/prefect/_internal/buildx.py参数清理decode等 docker-py 专属 kwarg 会被剔除避免误传标签收集主tag与extra_tags合并为完整标签列表重试逻辑复用完全复用了 docker-py 路径的容错机制——最多重试_BUILD_MAX_RETRIES3 次当错误信息命中_TRANSIENT_ERROR_PATTERNS502 Bad Gateway、503 Service Unavailable、500 Internal Server Error、i/o timeout、TLS handshake timeout、connection reset、context deadline exceeded见 src/prefect/utilities/dockerutils.py时按_BUILD_RETRY_DELAY_BASE ** (attempt 1)2/4/8 秒指数退避重试src/prefect/_internal/buildx.py。单次构建执行_buildx_build_oncesrc/prefect/_internal/buildx.py调用python_on_whales.docker.buildx.build(context_path..., file..., tags..., pull..., labels..., push..., platforms...)并将DockerException统一转换为 Prefect 的BuildError。返回值语义需要特别注意单平台非 push 构建返回Image对象取output.id如sha256:abc...作为镜像 ID多平台 push 构建返回None镜像只存在于 registry本地无镜像此时返回tags[0]作为合成标识让调用方知道构建已成功。buildx_push_image用于推送先前以单平台方式构建未使用pushTrue的本地镜像src/prefect/_internal/buildx.pydef buildx_push_image( name: str, tag: Optional[str] None, stream_progress_to: Optional[TextIO] None, ) - None:拼接name:tag后调用python_on_whales.docker.image.push()DockerException转换为OSError并支持通过stream_progress_to输出Pushing .../Pushed ...进度信息。兼容垫片src/prefect/docker/_buildx.py 是一个纯兼容层内部模块整合后buildx 工具函数迁移至prefect._internal.buildx该垫片重新导出buildx_build_image与buildx_push_image确保独立发布、可能锁定旧版 Prefect 的prefect-docker集成包继续可用。测试与验证策略该方案配套了完整的测试矩阵当前仓库均已落地单元测试tests/docker/test_buildx.py通过unittest.mock.patch模拟 python-on-whales无需真实 Docker daemon覆盖基础构建断言context_path、tags、pushFalse正确传递IMAGE_LABELS自动应用、自定义标签与IMAGE_LABELS合并kwargs 透传secrets、ssh、cache_from、cache_to原样到达docker.buildx.build单平台构建 →platforms[linux/amd64]多平台构建在pushFalse时抛ValueErrorpushTrue时返回 tag 且传递pushTrue构建失败DockerException转换为BuildError缺失/不存在的 context 抛出ValueError瞬态错误重试502 Bad Gateway首次失败后自动重试成功验证time.sleep触发decodeTrue参数被剥离推送路径带/不带 tag 的 push、DockerException转OSError、进度流输出。DockerImage 分发测试tests/docker/test_docker_image.py 覆盖默认后端为docker-py、build_backendbuildx正确存储、非法取值抛ValueError、buildx 分发到buildx_build_image、build_kwargs 正确转发、pushTrue构建后push()为 no-op、buildx push 分发到buildx_push_image。服务级测试tests/docker/test_image_builds.py 计划补充pytest.mark.service(docker)标记的真实构建用例验证 buildx 后端能返回镜像 ID、正确打标签并流式输出构建进度。推出计划与已决策事项设计文档明确了三阶段推出路径Phase 1当前以build_backendbuildx作为 opt-in 能力发布默认仍为docker-pyPhase 2经用户验证后考虑在检测到 python-on-whales 已安装时自动切换默认后端auto-detectPhase 3若 Docker 最终移除 legacy builder 路径将默认值迁移至 buildx 并弃用 docker-py 后端。文档记录的已决策事项Resolved Decisions不新增PREFECT_DOCKER_BUILD_BACKEND设置——build_backend目前仅作为参数存在如有需求可在后续以设置项补充构建推送一体化——确定支持build()中pushTrue即docker buildx build --push单步完成多平台构建必需、单平台构建更高效版本下限python-on-whales0.81。该能力已随 Prefect 3.6 发布见 版本发布记录 中 Add opt-in BuildKit/buildx support via python-on-whales 条目API 参考见 DockerImage API 文档 与 部署步骤 API 文档。边界、限制与注意事项默认路径不变不安装buildxextra 时build_backend保持docker-py行为与之前完全一致多平台强制推送多平台构建必须pushTrue否则报错——这是 buildx 的固有约束不是实现缺陷运行环境前提从实现方式可以推断buildx 后端依赖环境中的dockerCLI 与 buildx 插件可用python-on-whales 直接包装 CLI且DockerWorker的容器运行行为不受影响使用--mount、secret、SSH 等特性还需要构建侧 Dockerfile 开启# syntaxdocker/dockerfile:1等 BuildKit 语法指令错误信息导向遇到推送被拒时docker-py 路径的辅助提示检查docker login、镜像名不含空格等在 buildx 路径同样值得遵循buildx 相关的DockerException会被转换为BuildError/OSError便于 Prefect 侧统一处理与重试。【免费下载链接】prefectPrefect is a workflow orchestration framework for building resilient data pipelines in Python.项目地址: https://gitcode.com/GitHub_Trending/pr/prefect创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表