feat(worker): opt-in container-image runtime for GPU apps (single-machine) - #156
Merged
Conversation
…hine)
Add an opt-in path to run a Ray Serve replica inside a prebuilt container
image instead of the default pip/py_modules runtime. Pip stays the
recommended default; this is strictly gated behind the worker flag
--enable-container-runtime and the @bioengine.app(container_image=…) param.
- decorators: container_image= param drops a {"container": {"image": …}}
marker into runtime_env; raises if combined with pip (Ray forbids mixing
a container runtime_env with pip/py_modules).
- bootstrap: a container branch in build_and_run_application builds a
minimal runtime_env ({container, env_vars} only — the sole keys Ray
permits alongside container) and returns before the normal source/hook
injection. The image is the sole source of code (bioengine + app source
baked on PYTHONPATH). GPU wiring rides in podman run_options:
--device nvidia.com/gpu=all + LD_LIBRARY_PATH to the driver libs.
- ray_cluster: when enabled, generate a podman-4.9.3-compatible CDI spec at
startup (nvidia-ctk, --disable-hook update-ldcache, down-version to
cdiVersion 0.6.0, strip additionalGids + its orphaned bare-int items) and
export the driver-lib dir for the replica LD_LIBRARY_PATH.
- worker/__main__: --enable-container-runtime flag (Ray Cluster group,
flows straight into RayCluster via ray_cluster_config).
- docker/worker-container-runtime.Dockerfile: dedicated rootful worker image
(ubuntu:24.04 for podman 4.9.3, nvidia-container-toolkit, Ray keep-id
patch). Kept a separate image from the lean python:3.11-slim prod worker
on purpose — the podman pin forces the heavier base and its CVE surface
should stay out of the production worker's scan report.
Single-machine mode only; KubeRay path unaffected.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Manual, on-demand builder for the container-as-runtime worker image (docker/worker-container-runtime.Dockerfile). Deliberately not wired into docker-publish-worker.yml — the niche, heavier ubuntu:24.04 variant is built only when needed and published as a separate GHCR package sharing the worker version. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Opt-in container-image-as-Ray-Serve-runtime for BioEngine GPU apps, single-machine mode only. An app can declare
@bioengine.app(container_image=…)and its replica runs inside that prebuilt image instead of the default pip/py_modules runtime — for heavy or conflicting dependency stacks that are better shipped as an image than resolved per-actor.Pip/py_modules stays the recommended default. The whole path is gated behind the new worker flag
--enable-container-runtime(off by default) plus the per-appcontainer_image=param. With the flag off, nothing here changes worker behaviour, and the KubeRay/multi-node path is untouched.Proven end-to-end on a throwaway rootful single-machine worker:
deploy_app→ HEALTHY,version_verified=True, GPU probe returns a real CUDA context (torchcompute on an RTX 3090, not an NVML false-positive).What's in the PR
Framework (
bioengine/)_app/decorators.py—container_image=param; drops a{"container": {"image": …}}marker intoruntime_env. RaisesValueErrorif combined withpip(Ray forbids mixing a container runtime_env with pip/py_modules)._app/bootstrap.py— a container branch inbuild_and_run_applicationbuilds a minimal runtime_env ({container, env_vars}— the only keys Ray permits alongsidecontainer) and returns before the normal source/hook injection. The image is the sole source of code (bioengine + app source baked onPYTHONPATH). GPU wiring rides in podmanrun_options:--device nvidia.com/gpu=all(when GPU requested) +LD_LIBRARY_PATHto the driver libs.cluster/ray_cluster.py— when enabled, generate a podman-4.9.3-compatible CDI spec at startup (nvidia-ctk,--disable-hook update-ldcache, down-version tocdiVersion 0.6.0, stripadditionalGids+ its orphaned bare-int list items) and export the driver-lib dir for the replicaLD_LIBRARY_PATH. No-op with a warning if not root ornvidia-ctkis absent.worker/__main__.py—--enable-container-runtimeflag (Ray Cluster group; flows straight intoRayClusterviaray_cluster_config).Image (
docker/)worker-container-runtime.Dockerfile— a dedicated rootful worker image (ubuntu:24.04for podman 4.9.3,nvidia-container-toolkit, a build-time Ray patch dropping the hardcoded--userns=keep-idflag, guarded to fail the build loudly if a Ray bump renames the anchor).Design notes
python:3.11-slimvariant. Theubuntu:24.04base is forced by the podman 4.9.3 pin (podman 5.x rejects--pid=hoston cgroup-v1 hosts; Debian slim's apt has neither 4.9.3). The prod worker stays lean onpython:3.11-slim— its smaller CVE surface shouldn't be regressed to serve a niche opt-in path.bioengine-worker-container-runtime:X.Y.Zsharing the worker version, so the heavy image's scan findings stay out of thebioengine-workerpackage. The CI build+tag step is deferred.Scope / not included
runtime.container_imagefield, docs/skill updates, CI publish wiring, KubeRay/multi-node.Status
Draft — dev-image validation + version bump before marking ready.