Complete the image builder abstraction and add podman support#4651
Complete the image builder abstraction and add podman support#4651stefannica wants to merge 12 commits intodevelopfrom
Conversation
AlexejPenner
left a comment
There was a problem hiding this comment.
Tiny nit - otherwise 👍
| else: | ||
| image_name_or_digest = target_image_name |
There was a problem hiding this comment.
Note for @schustmi : this means that unless you have a local image builder, the parent image will not be re-tagged and pushed to the container registry. I don't fully understand the implications of this. Should we do something else here, like warn the user ?
There was a problem hiding this comment.
I mean we had a solution that was working for all image builders before, maybe we just use that one? 😅
| and stack.image_builder | ||
| and stack.image_builder.is_building_locally |
There was a problem hiding this comment.
Another note for @schustmi: this means that when a remote image builder is used, the parent image's digest will not be included in the hash. What is the impact of this ? Should I log a warning here or something ?
There was a problem hiding this comment.
See my other comments, this method makes simply no sense on the image builder and belongs on the container registry, where this PR for some reason removes it.
a70d35d to
c83c722
Compare
| else: | ||
| image_name_or_digest = target_image_name |
There was a problem hiding this comment.
I mean we had a solution that was working for all image builders before, maybe we just use that one? 😅
| and stack.image_builder | ||
| and stack.image_builder.is_building_locally |
There was a problem hiding this comment.
See my other comments, this method makes simply no sense on the image builder and belongs on the container registry, where this PR for some reason removes it.
Documentation Link Check Results✅ Absolute links check passed |
854f399 to
b644462
Compare
Describe changes
The responsibilities related to container image management involving OCI-compatible clients such as Docker were spread across several components (the image builder, the container registry) and the old
zenml.utils.docker_utilshelpers. That layout made it hard to extend ZenML for engines that are not the Docker daemon + docker-py stack (for example Podman).This change introduces a dedicated
ContainerEngineabstraction inzenml.container_engines, withDockerContainerEngineandPodmanContainerEngineimplementations. Local OCI operations—build, tag, push, “is this image local?”, and repository digest resolution live on that surface. Engines are not bound to a single registry in their constructors; registry credentials and validation flow through the stack’s container registry (and connector-driven CLI login where applicable) on each operation.LocalImageBuilderstays the stack component users configure for local builds, but it resolves the active backend viaget_container_engine(), so there is still a single local image builder flavor—no separate “local Podman” flavor.Users choose Docker vs Podman through global ZenML configuration: the
container_enginessetting (typed asContainerEngineType:dockerorpodman), also overridable viaZENML_CONTAINER_ENGINE. When unset, ZenML auto-detects (Docker first, then Podman). Default effective behavior remains Docker-first for existing environments.Implementation details
zenml.container_enginesprovides:ContainerEngine(ABC) — shared contract and helpers such as.parse_dockerignore()/.sanitize_tag()where they belong for all engines.DockerContainerEngine— Docker CLI and docker-py (build via API or optionaldocker buildsubprocess, push, inspect, registry digest lookup when meaningful).PodmanContainerEngine— Podman CLI only (build with tar-on-stdin likedocker build -,podman tag,podman image inspectfor the local-image heuristic,podman login+podman push).get_container_engine()/check_container_engine()centralize selection, availability checks, and (for call sites that must pin the daemon API)get_container_engine(ContainerEngineType.DOCKER).LocalImageBuilder.buildusesget_container_engine()for build and push; pipeline utilities (PipelineDockerImageBuilder,BuildConfiguration.compute_settings_checksum, etc.) call the same engine API for tag, parent pull vs local heuristics, andget_image_repo_digestwhere the checksum should include a parent digest for local builds.IMPORTANT: Podman still cannot reliably report remote manifest digests (see containers/podman#14779), so the Podman path continues to use uniquely generated tags as a stable push identity—aligned with the approach already used elsewhere (e.g. AWS image builder).
The container registry stack component remains required for pushes in this flow and is still used to:
prepare_image_pushand any flavor-specific pre-push logic.zenml.utils.docker_utilsis removed from the library. Behavior that still belongs in product code now lives underzenml.container_engines(base + Docker implementation). Remaining ad-hoc helpers used only by the tests deployment harnesses (for examplebuild_image-style utilities) have been replaced with the use ofDockerContainerEngine.build.Docker-specific integrations that must talk to the Docker daemon API (Docker deployer, local Docker orchestrator, container service, server Docker provider, CLI checks, BentoML, Docker service connector verification, etc.) are updated to use
container_engines—typicallyget_container_engine(ContainerEngineType.DOCKER)where a Podman backend would not be valid—instead of importingdocker_utils.Pre-requisites
Please ensure you have done the following:
developand the open PR is targetingdevelop. If your branch wasn't based on develop read Contribution guide on rebasing branch to develop.Types of changes