Skip to content

Complete the image builder abstraction and add podman support#4651

Open
stefannica wants to merge 12 commits intodevelopfrom
feature/podman-image-builder
Open

Complete the image builder abstraction and add podman support#4651
stefannica wants to merge 12 commits intodevelopfrom
feature/podman-image-builder

Conversation

@stefannica
Copy link
Copy Markdown
Contributor

@stefannica stefannica commented Mar 29, 2026

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_utils helpers. 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 ContainerEngine abstraction in zenml.container_engines, with DockerContainerEngine and PodmanContainerEngine implementations. 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.

LocalImageBuilder stays the stack component users configure for local builds, but it resolves the active backend via get_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_engines setting (typed as ContainerEngineType: docker or podman), also overridable via ZENML_CONTAINER_ENGINE. When unset, ZenML auto-detects (Docker first, then Podman). Default effective behavior remains Docker-first for existing environments.

Implementation details

zenml.container_engines provides:

  • 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 optional docker build subprocess, push, inspect, registry digest lookup when meaningful).
  • PodmanContainerEnginePodman CLI only (build with tar-on-stdin like docker build -, podman tag, podman image inspect for 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.build uses get_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, and get_image_repo_digest where 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:

  • Validate that the image name matches the configured registry URI.
  • Run prepare_image_push and any flavor-specific pre-push logic.
  • Supply credentials for private registries.

zenml.utils.docker_utils is removed from the library. Behavior that still belongs in product code now lives under zenml.container_engines (base + Docker implementation). Remaining ad-hoc helpers used only by the tests deployment harnesses (for example build_image-style utilities) have been replaced with the use of DockerContainerEngine.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—typically get_container_engine(ContainerEngineType.DOCKER) where a Podman backend would not be valid—instead of importing docker_utils.

Pre-requisites

Please ensure you have done the following:

  • I have read the CONTRIBUTING.md document.
  • I have added tests to cover my changes.
  • I have based my new branch on develop and the open PR is targeting develop. If your branch wasn't based on develop read Contribution guide on rebasing branch to develop.
  • IMPORTANT: I made sure that my changes are reflected properly in the following resources:
    • ZenML Docs
    • Dashboard: Needs to be communicated to the frontend team.
    • Templates: Might need adjustments (that are not reflected in the template tests) in case of non-breaking changes and deprecations.
    • Projects: Depending on the version dependencies, different projects might get affected.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Other (add details above)

@github-actions github-actions bot added internal To filter out internal PRs and issues enhancement New feature or request labels Mar 29, 2026
@stefannica stefannica removed the request for review from Json-Andriopoulos March 30, 2026 07:35
@stefannica stefannica added the release-notes Release notes will be attached and used publicly for this PR. label Mar 30, 2026
Copy link
Copy Markdown
Contributor

@AlexejPenner AlexejPenner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tiny nit - otherwise 👍

@stefannica stefannica added the run-slow-ci Tag that is used to trigger the slow-ci label Mar 31, 2026
@stefannica stefannica requested a review from AlexejPenner March 31, 2026 13:33
Comment on lines +264 to +265
else:
image_name_or_digest = target_image_name
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean we had a solution that was working for all image builders before, maybe we just use that one? 😅

Comment on lines +115 to +116
and stack.image_builder
and stack.image_builder.is_building_locally
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@stefannica stefannica force-pushed the feature/podman-image-builder branch from a70d35d to c83c722 Compare March 31, 2026 15:13
Comment on lines +264 to +265
else:
image_name_or_digest = target_image_name
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean we had a solution that was working for all image builders before, maybe we just use that one? 😅

Comment on lines +115 to +116
and stack.image_builder
and stack.image_builder.is_building_locally
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

Documentation Link Check Results

Absolute links check passed
Relative links check passed
Last checked: 2026-04-07 17:43:33 UTC

@stefannica stefannica requested a review from schustmi April 7, 2026 16:00
@stefannica stefannica force-pushed the feature/podman-image-builder branch from 854f399 to b644462 Compare April 7, 2026 17:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request internal To filter out internal PRs and issues release-notes Release notes will be attached and used publicly for this PR. run-slow-ci Tag that is used to trigger the slow-ci

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants