Skip to content

bug(podman): resource admission rejects image-declared VOLUMEs; lacks Docker parity #3890

Description

@matthewgrossman

User Story

As an operator running a Podman gateway with resource admission enabled, I want sandboxes created from images that declare VOLUME to be admitted the same way the Docker driver admits them, so that ordinary OCI images work regardless of which local container runtime backs the gateway.

Problem Statement

When resource_admission is enabled, the Podman driver rejects any sandbox whose workload image declares a VOLUME. Podman creates an anonymous local volume for each image-declared path. admit_container_resources (crates/openshell-driver-podman/src/driver.rs) treats that volume as an externally attached volume: it runs label admission on it and adds it to the actual inventory. The volume is not in the recorded openshell.ai/resource-admission-identities set, so the actual != expected check fails with external volume identity or attachment inventory changed. The same check runs every 30 seconds in reconcile_resource_admission.

The Docker driver already handles this case (crates/openshell-driver-docker/src/lib.rs):

  • build_container_create_body_for_image validates every image-declared volume, for custom and /sandbox workdirs alike. It rejects targets that overlap reserved OpenShell paths or the /.openshell/channel boundary mount, or that cover the resolved workspace.
  • It records the declared targets in the openshell.ai/private-image-volume-targets workload label.
  • admit_container_resources accepts a volume that is not in the expected identity set only when its mount destination is one of those recorded targets and it is a local volume with no driver options. Otherwise it fails with image-private volume backing changed.

Podman has no equivalent. After #3801 lands, Podman reads Config.Volumes only to reject image volumes that cover a custom WORKDIR or overlap reserved paths. It does not validate image volumes for /sandbox fallback images, and it does not record them for admission.

Impact / Why This Matters

  • Images are rejected. Operators who enable Podman resource admission cannot run common images that declare VOLUME, such as many database, language-runtime, and framework base images. The same images work on a Docker gateway.
  • The workaround is poor. Operators must rebuild images without VOLUME or disable resource admission. Rebuilding is often impossible for third-party images; disabling admission removes a security control.
  • Reserved paths are not checked for fallback images. A Podman image with a /sandbox workdir can declare a VOLUME over reserved OpenShell paths without being rejected up front, while Docker rejects it.
  • The drivers diverge. Docker and Podman now share the OCI WORKDIR contract (feat: honor OCI WorkingDir for Docker and Podman workspaces #2526, feat(podman): honor OCI image working directories #3801). Image VOLUME handling is the remaining gap in the image contract.

Acceptance Criteria

  • With resource admission enabled, a Podman sandbox from an image that declares a VOLUME below the workspace, or elsewhere outside reserved paths, is admitted at create time and by periodic reconciliation.
  • Podman validates image-declared volumes for all images, including the /sandbox fallback, with the same rules and error messages as Docker: no overlap with reserved OpenShell paths or Podman workload control paths (/.openshell, the supervisor CA runtime root), and no volume covering the resolved workspace.
  • An image-volume mount is admitted only if its destination matches a target recorded at create time and it is a local volume with no driver options. Otherwise admission fails, for example if the volume backing or destination changed or a named external volume was attached at that path.
  • Docker and Podman read the private-image-volume-targets label name from one shared constant in openshell-core (for example, resource_admission::PRIVATE_IMAGE_VOLUME_TARGETS_LABEL).
  • Unit tests cover Podman admission accepting a recorded local anonymous volume and rejecting a changed backing or an unrecorded destination.
  • An E2E test on a Podman gateway with resource admission enabled creates a sandbox from an image with a VOLUME, writes to it, and passes reconciliation.
  • The Podman README, the gateway configuration docs, and skills/debug-openshell-cluster/SKILL.md describe how image VOLUME declarations interact with resource admission.

Reproduction Steps

Derived from code reading on main, not yet reproduced on a live gateway.

  1. Configure a Podman gateway with resource_admission enabled.
  2. Build an image with a volume declaration:
    FROM ubuntu:24.04
    RUN mkdir -p /data && chown 1000:1000 /data
    VOLUME /data
    USER 1000:1000
  3. Run openshell sandbox create --from <image> -- sleep infinity.
  4. Expected: the sandbox starts, as it does on a Docker gateway with admission enabled. Actual: creation fails admission with external volume identity or attachment inventory changed, or with a label admission denial for the anonymous volume.

Environment

  • OpenShell: main at c0eb3db, with the Podman OCI WORKDIR support from feat(podman): honor OCI image working directories #3801
  • Runtime: Podman driver (rootful or rootless) with resource_admission enabled
  • Docker comparison: openshell-driver-docker admit_container_resources and build_container_create_body_for_image

Notes

An earlier revision of #3801 prototyped this but recorded image volumes only for custom WORKDIR images. The follow-up should record and validate them for every image, as Docker does. Podman removes anonymous volumes with the container (DELETE ...?volumes=true), so no extra cleanup should be needed.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions