Skip to content

Configurable Container Runtime (Docker/Podman) - #27

Open
Hadar301 wants to merge 4 commits into
validatedpatterns-sandbox:mainfrom
Hadar301:feat/configurable-container-runtime
Open

Configurable Container Runtime (Docker/Podman)#27
Hadar301 wants to merge 4 commits into
validatedpatterns-sandbox:mainfrom
Hadar301:feat/configurable-container-runtime

Conversation

@Hadar301

Copy link
Copy Markdown
Collaborator

Jira: https://redhat.atlassian.net/browse/APPENG-6041


Summary

Makes the container runtime inside the gateway VM configurable via a single Helm value (containerRuntime: docker|podman). Ships two pre-built golden images — a Docker variant for NemoClaw and a Podman variant for openclaw/opencode — and routes all runtime-specific behavior through the toggle. Switching runtimes requires only a values change + VM recreate; no golden image rebuild is needed.


What changed

charts/openshell-saw

  • values.yaml — new containerRuntime: docker field (default); source.dataSource cleared so it auto-derives from the runtime
  • templates/_helpers.tpl — new openshell-sandbox.dataSourceName helper: resolves openshell-gateway-docker for docker, openshell-gateway for podman, with explicit override support
  • templates/virtualmachine.yaml — DataSource name now uses the helper
  • templates/cloudinit-sandbox.yamlOPENSHELL_DRIVERS set from containerRuntime instead of hardcoded docker
  • templates/configmap-scripts.yaml — multiple changes across all setup scripts:
    • RUNTIME variable injected at the top of run-setup.sh, setup-nemoclaw.sh, setup-dashboard.sh, setup-workspaces.sh
    • All docker pull/create/cp/rm/run/stop/logs replaced with ${RUNTIME}
    • Registry auth block (docker login, insecure-registries daemon config) wrapped in a Docker-only conditional; Podman path prints a clear skip message
    • BUILD_NS and NEMOCLAW_CLI_IMAGE gated so they don't cause unbound-variable errors on the Podman path
    • NemoClaw+Podman validation guard: setup exits immediately with a clear error if containerRuntime=podman and onboardCli=nemoclaw
    • setup-dashboard.sh exits gracefully (not with exit 1) when oidc.issuerUrl is not configured, preventing spurious Job retries in standalone deployments without Keycloak
    • models.mode in the openclaw config set to replace (only configured providers shown in TUI) instead of the invalid custom

image-builder-charts/helm/openshell-gateway-image

  • values.yaml — new containerRuntime: docker field
  • templates/buildconfig.yaml — branches on containerRuntime:
    • Docker: removes Podman, installs Docker CE, enables docker.service, derives GRPC endpoint from docker network inspect bridge (172.17.0.1)
    • Podman: keeps Fedora-default Podman, enables user-level podman.socket (after the user systemd bus is ready), sets OPENSHELL_PODMAN_SOCKET in gateway.env, derives GRPC endpoint from podman network inspect podman (10.88.0.1)
    • $imageName derived from runtime: openshell-gateway-docker (Docker) or openshell-gateway (Podman)
  • templates/golden-image.yaml and templates/imagestream.yaml — use $imageName for all resource names

Makefile and scripts

  • Makefile-quickstartCONTAINER_RUNTIME and IMAGE_NAME variables; build-openshell-gateway uses IMAGE_NAME throughout; openshell-saw-create forwards CONTAINER_RUNTIME and GOVERNANCE_ENABLED; configure-gateway is now idempotent (removes stale entry before re-adding)
  • scripts/openshell-saw-create.sh — accepts CONTAINER_RUNTIME and GOVERNANCE_ENABLED env vars, passes both to helm
  • scripts/e2e-test.sh (line 304) and tests/test-bootc-e2e.sh (line 346) — runtime version check uses the configured runtime instead of the stale podman --version

macOS copy-images fix

make copy-images fails on macOS because podman runs inside a VM and large-layer TCP uploads to the OpenShift external registry route are dropped mid-transfer. On uname -s == Darwin, the target now delegates to an in-cluster skopeo Job that pushes directly to image-registry.openshift-image-registry.svc:5000, bypassing the external route entirely.

New files: scripts/mirror-images-incluster.sh, scripts/mirror-images-rbac.yaml, scripts/mirror-images-job.yaml

Docs

  • docs/container-runtime.md — new doc covering: runtime comparison table, golden image build commands, deploy commands, TUI connection steps (mTLS cert copy, port-forward, ssh-proxy), and known limitations (NemoClaw incompatibility, inference.local, rootless Podman caveats)

E2E validation (Docker path, clean first-time install)

Tested against cluster-7brvw.dyn.redhatworkshops.io:

Step Result
make build-openshell-gateway CONTAINER_RUNTIME=docker openshell-gateway-docker ImageStream + DataSource created
CDI golden image import ✅ DataVolume Succeeded
Setup Job — DataSource: openshell-gateway-docker
Setup Job — docker login to internal registry
Setup Job — docker pull/create/cp/rm binary extraction
Setup Job — nemoclaw CLI installed
Setup Job — sandbox created from nemoclaw-sandbox:latest
Setup Job — openclaw gateway ready
Setup Job — dashboard skipped cleanly (no Keycloak)
run-create OK / Setup complete
TUI — openclaw responded to prompts

Podman path validation:

  • NemoClaw preflight: ✗ Docker is not reachable — correct expected failure
  • Binary extraction via podman pull/create/cp/rm — confirmed in logs
  • OPENSHELL_DRIVERS=podman in cloud-init — confirmed
  • DataSource: openshell-gateway — confirmed

Notes for reviewers

  • NemoClaw + openshell 0.0.99: NemoClaw's inference.local routing (nemoclaw onboard step 4) fails with externally-supervised gateways running 0.0.99+. The setup Job's fallback creates the inference provider and sandbox via openshell provider create + openshell sandbox create, which is sufficient for TUI use. This is a known upstream limitation unrelated to this PR.
  • nemoclaw-sandbox image: Must be available in the internal registry before the setup Job runs. On first deploy, use make copy-images (Linux) or it runs automatically on macOS via the new in-cluster Job path.
  • TUI mTLS: The gateway cert is valid only for 127.0.0.1. TUI access requires copying the client cert from the VM (virtctl scp) and port-forwarding the gateway service. Steps documented in docs/container-runtime.md. A follow-up improvement would be publishing the client cert as a k8s Secret from the setup Job to eliminate the virtctl dependency.

Hadar301 and others added 4 commits August 14, 2026 07:35
Introduces containerRuntime: docker|podman toggle across the chart stack.
Switching runtimes requires only a values change + VM recreate — no golden
image rebuild needed when both images are pre-built.

Key changes:
- openshell-saw values: containerRuntime (default: docker), dataSource
  auto-derived from runtime via new openshell-sandbox.dataSourceName helper
- cloud-init: OPENSHELL_DRIVERS set from containerRuntime value
- configmap-scripts: RUNTIME variable injected into all setup scripts;
  registry auth and docker login wrapped in docker-only conditional;
  binary extraction (pull/create/cp/rm) and dashboard systemd units use
  ${RUNTIME} throughout; NemoClaw+Podman guard at setup start
- image-builder-charts: $imageName derived from containerRuntime
  (openshell-gateway-docker vs openshell-gateway); virt-customize branches
  on runtime for Docker CE vs Podman; user-setup.sh enables user-level
  podman.socket after the user bus is ready; OPENSHELL_PODMAN_SOCKET and
  OPENSHELL_GRPC_ENDPOINT derived per runtime
- Makefile-quickstart: CONTAINER_RUNTIME and IMAGE_NAME variables;
  build-openshell-gateway and openshell-saw-create forward runtime;
  configure-gateway is now idempotent (remove-before-add)
- e2e-test.sh, test-bootc-e2e.sh: runtime-aware binary version check
- docs/container-runtime.md: new doc covering both runtime paths,
  build/deploy commands, and known limitations

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…gured

setup-dashboard.sh previously hard-exited (exit 1) when OIDC_ISSUER was
unset, causing the setup Job to fail and retry even when dashboard.enabled
is true but Keycloak is not deployed. Now exits cleanly with an explanatory
message, matching the pattern of other optional setup steps.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Documents the mTLS cert setup, port-forward, and ssh-proxy command
needed to reach the openclaw TUI from a local workstation. Notes the
virtctl dependency and the follow-up improvement (publish certs as a
k8s Secret to remove that dependency).

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
podman on macOS runs inside a VM — TCP connections to the OpenShift
external registry route are dropped mid-upload for large layers (>30 MB),
making `make copy-images` unreliable.

On macOS, `copy-images` now detects `uname -s == Darwin` and delegates to
scripts/mirror-images-incluster.sh, which runs skopeo inside the cluster
against the internal registry service (bypassing the external route
entirely). On Linux the original oc-image-mirror path is unchanged.

New files:
- scripts/mirror-images-incluster.sh — orchestrates per-image Jobs
- scripts/mirror-images-rbac.yaml   — ServiceAccount + RoleBinding (static)
- scripts/mirror-images-job.yaml    — Job template (envsubst-rendered per image)

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@Hadar301
Hadar301 requested a review from sauagarwa August 14, 2026 15:40
@Hadar301 Hadar301 self-assigned this Aug 14, 2026

@sauagarwa sauagarwa left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Good PR overall — clean single-toggle design, solid guard rails. A few things to address:

1. In-cluster mirror Job: use oc image mirror instead of skopeo

The Job already runs inside the cluster, so oc image mirror can push directly to image-registry.openshift-image-registry.svc:5000 — same as skopeo but without introducing a new tool. This lets you:

  • Use registry.redhat.io/openshift4/ose-cli instead of registry.redhat.io/ubi8/skopeo
  • Drop the anyuid SCC grant (oc image mirror doesn't need root)
  • Keep tooling consistent with the Linux path

Applies to: scripts/mirror-images-job.yaml, scripts/mirror-images-incluster.sh, scripts/mirror-images-rbac.yaml

2. Podman socket wait loop needs a warning on timeout

In buildconfig.yaml, the Podman socket wait loop silently continues if the socket never appears after 15s. If the gateway then can't reach Podman, the failure surfaces later with no clue about the root cause. Add a warning:

for _ in $(seq 1 15); do
  if [[ -S "/run/user/${USER_UID}/podman/podman.sock" ]]; then break; fi
  sleep 1
done
if [[ ! -S "/run/user/${USER_UID}/podman/podman.sock" ]]; then
  echo "WARNING: Podman socket not found after 15s — gateway may fail to start" >&2
fi

3. models.mode = 'replace' is unrelated to the runtime toggle

The fix in configmap-scripts.yaml (changing the invalid custom to replace) is correct but unrelated to container runtime configurability. Consider splitting it into a separate commit for cleaner bisect history.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants