Skip to content

fix(gpu): select one CDI GPU by default for Docker and Podman #1477

Description

@elezar

Description

Update Docker and Podman GPU sandbox defaults so --gpu prefers one CDI GPU device instead of defaulting to nvidia.com/gpu=all.

This is part of the GPU roadmap in #1444. --gpu means the active driver's default GPU behavior, and for GPU-enabled drivers that default should inject or allocate one suitable GPU when the runtime supports individual device selection.

Context

Parent roadmap: #1444

Current local-container behavior maps a GPU request with no explicit gpu_device to nvidia.com/gpu=all through the shared CDI helper. That makes Docker and Podman inconsistent with Kubernetes and VM behavior, where a default GPU request maps to one GPU.

Docker has priority for implementation because OpenShell's Docker GPU path and CDI discovery are more mature today. Podman should be handled in the same task, but may require additional runtime support or an out-of-band CDI device discovery path. Upstream Podman behavior such as podman-container-tools/podman#28712 may be relevant.

Proposed Scope

  • Define local-container default GPU selection semantics for Docker and Podman.
  • Change Docker default --gpu behavior to prefer one CDI GPU device instead of nvidia.com/gpu=all.
  • Change Podman default --gpu behavior to prefer one CDI GPU device instead of nvidia.com/gpu=all.
  • Prefer runtime-reported CDI inventory when available.
  • Preserve explicit --gpu-device behavior as a driver-native advanced option.
  • Do not add multi-GPU count support in this task.
  • Do not require OpenShell-managed GPU assignment/exclusivity tracking in this task.

Target Behavior

Default GPU selection should use this order:

  1. If the runtime reports individual CDI GPU devices, select one individual device.
  2. If reliable CDI inventory is unavailable but individual device IDs are expected to work, fall back to nvidia.com/gpu=0.
  3. If the runtime/platform only reports or supports nvidia.com/gpu=all, such as some WSL2-based setups, use nvidia.com/gpu=all as a compatibility fallback.

Additional behavior:

  • openshell sandbox create --gpu ... on Docker injects one CDI GPU device when individual device selection is available.
  • openshell sandbox create --gpu ... on Podman injects one CDI GPU device when individual device selection is available.
  • openshell sandbox create --gpu --gpu-device nvidia.com/gpu=0 ... continues to pass the explicit CDI device ID through.
  • The fallback to nvidia.com/gpu=all should be intentional and documented, not the default for platforms with individual device selection.
  • Non-zero gpu_count remains unsupported unless a driver explicitly implements count-based allocation.

Out of Scope

This task fixes default GPU device selection cardinality. It does not require OpenShell to track active GPU assignments or prevent two OpenShell sandboxes from selecting the same default GPU.

If multiple sandboxes are created concurrently, selecting the same default fallback device is acceptable until a separate allocation/exclusivity task is implemented.

Open Questions

  • Where should CDI inventory discovery live: shared OpenShell core helper, driver-specific code, or both?
  • What should Podman use as the authoritative CDI device inventory source before runtime-level enumeration is reliable?
  • Should assignment/exclusivity tracking be added later at the driver level or as part of a broader resource allocation model?

Definition of Done

  • Docker default --gpu prefers one individual CDI GPU device when available.
  • Podman default --gpu prefers one individual CDI GPU device when available.
  • If reliable CDI inventory is unavailable and individual IDs are expected to work, default selection falls back to nvidia.com/gpu=0.
  • If individual selection is unavailable, nvidia.com/gpu=all remains available as a documented compatibility fallback.
  • Explicit --gpu-device pass-through behavior is preserved for Docker and Podman.
  • Tests cover individual-device default selection, fallback selection, and explicit device pass-through.
  • Docs describe Docker/Podman default GPU behavior, compatibility fallback behavior, and --gpu-device as an advanced driver-native option.

Activity

  1. elezar commented on Jun 1, 2026

    @elezar
    MemberAuthor

    🏗️ build-plan

    Implementation Plan

    Issue type: fix
    Complexity: Medium
    Confidence: High - Docker uses daemon inventory and Podman local Linux
    inventory is derived directly from /dev/nvidiaN; remote Podman inventory is
    explicitly out of scope.

    Summary

    Update local-container GPU selection so a bare --gpu request resolves to one
    CDI GPU device by default instead of nvidia.com/gpu=all, using
    driver-owned round-robin selection to rotate default requests across available
    IDs without tracking active ownership. Docker and Podman share CDI selection
    helpers, while inventory collection stays driver-specific: Docker uses
    daemon-reported CDI inventory, and local Linux Podman maps /dev/nvidiaN
    nodes to nvidia.com/gpu=N. nvidia.com/gpu=all remains an intentional
    compatibility path for all-only runtimes. Docker indexed IDs and UUID-style
    IDs are treated as alternate naming families for the same device pool and are
    not mixed.

    Scope

    • crates/openshell-core/src/gpu.rs: Add shared CDI GPU inventory
      normalization, fallible default-selection, and concurrency-safe round-robin
      cursor helpers.
    • crates/openshell-driver-docker/src/lib.rs: Capture Docker daemon CDI GPU
      inventory from docker.info() and use it when building CDI device requests.
      Treat missing, null, empty, or non-GPU Docker inventory as a clear
      precondition error for bare --gpu while preserving explicit
      --gpu-device pass-through when Docker CDI support is enabled. Normalize
      mixed indexed/UUID-style CDI IDs to one available naming family, preferring
      indexed IDs when present. Add a Docker-owned round-robin cursor and ensure
      validation/preview paths do not advance it.
    • crates/openshell-driver-docker/src/tests.rs: Cover individual default
      selection, missing/null inventory failure, all-only fallback, known-empty
      failure, mixed indexed/UUID-style normalization, UUID-style-only selection,
      cursor advancement/wrapping, validation no-advance behavior, and explicit
      device pass-through.
    • crates/openshell-driver-podman/src/driver.rs and
      crates/openshell-driver-podman/src/container.rs: Enumerate local
      /dev/nvidiaN nodes, map them to nvidia.com/gpu=N, carry that inventory
      into a driver-owned round-robin cursor and a fallible inventory-aware
      container spec builder. The inventory helper should be unit-testable with an
      injectable device root and ignore non-numeric NVIDIA control/helper nodes.
    • crates/openshell-driver-podman/src/container.rs/driver tests: Cover
      local /dev/nvidiaN inventory mapping, empty-inventory rejection, default
      selection, cursor advancement/wrapping, validation no-advance behavior, and
      explicit pass-through.
    • e2e/rust/tests/gpu_device_selection.rs: Update optional GPU e2e
      expectations so Docker uses daemon CDI inventory and Podman uses local
      /dev/nvidiaN inventory for the default device.
    • Docker/Podman docs and READMEs: Document the default, all-only
      compatibility path, missing-inventory failure behavior, and --gpu-device
      override behavior.

    Implementation Steps

    1. Add shared CDI GPU selection, round-robin cursor, and tests in
      openshell-core.
    2. Wire Docker daemon discovered-device inventory into Docker device request
      construction, normalizing indexed and UUID-style aliases into one available
      naming family, and add Docker driver-owned round-robin selection.
    3. Add Podman local /dev/nvidiaN inventory enumeration and Podman
      driver-owned round-robin selection.
    4. Update Docker and Podman unit tests for defaults, all-only compatibility,
      Docker mixed-name-family normalization, explicit pass-through,
      cursor advancement/wrapping, validation no-advance behavior, Docker's
      missing/empty inventory failure paths, and Podman's local empty-inventory
      rejection.
    5. Update optional GPU e2e expectations for Docker daemon inventory and
      Podman local /dev/nvidiaN inventory.
    6. Update docs.

    Test Plan

    • Unit tests: openshell-core, Docker driver tests, and Podman
      driver/container tests.
    • Integration tests: N/A - behavior is contained in driver spec/request
      builders.
    • E2E tests: Update existing GPU e2e tests. Run
      mise run e2e:docker:gpu and mise run e2e:podman:gpu only in a
      CDI-capable GPU environment; otherwise note the hardware gate.

    Risks & Constraints

    • Remote Podman does not currently report available CDI devices. For this
      task, Podman inventory is local Linux only via /dev/nvidiaN; future Podman
      remote CDI reporting can replace or augment that later.
    • Missing Docker DiscoveredDevices, known-empty Docker inventory, and empty
      local Podman inventory fail clearly for bare default requests instead of
      falling back.
    • All-only CDI runtimes must keep working through the compatibility fallback.
    • GetCapabilitiesResponse.gpu_count stays 0; this task does not implement
      public count reporting.
    • This is not allocation. The cursor can wrap to a CDI ID still used by an
      existing sandbox, and separate gateway/driver processes can choose the same
      ID.

    Documentation Impact

    • Update Docker/Podman GPU docs and driver READMEs.
    • No docs/reference/gateway-config.mdx update expected.
    • LSM compatibility: no expected SELinux/AppArmor behavior change.

    Revision 1 - initial plan

  2. self-assigned this
    on Jun 1, 2026
  3. moved this from Todo to In progress in OpenShell Roadmapon Jun 2, 2026
  4. elezar commented on Jun 2, 2026

    @elezar
    MemberAuthor

    🏗️ build-from-issue-agent

    Implementation Complete

    PR: #1675

    What was built

    Docker and Podman now use driver-owned CDI GPU inventory to select one default NVIDIA CDI GPU for bare --gpu requests. Explicit --gpu-device values continue to pass through unchanged.

    Tests

    • Unit: Core GPU inventory/round-robin tests; Docker inventory/default selection tests; Podman local inventory/default selection tests.
    • E2E: GPU device selection expectations updated and the GPU e2e target compiled with --no-run.
    • Pre-commit: mise run pre-commit passed.

    GPU e2e execution was environment-blocked locally: Docker reports only docker.com/gpu=webgpu, Podman is not installed, and /dev/nvidia0 is absent.

    Docs updated

    • docs/sandboxes/manage-sandboxes.mdx
    • docs/reference/sandbox-compute-drivers.mdx
    • crates/openshell-driver-docker/README.md
    • crates/openshell-driver-podman/README.md

    The issue will auto-close when the PR is merged.

  5. added
    state:pr-openedPR has been opened for this issue
    and removed on Jun 2, 2026
  6. moved this from In progress to Done in OpenShell Roadmapon Jun 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

state:agent-readyApproved for agent implementationstate:pr-openedPR has been opened for this issue

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions