-
Notifications
You must be signed in to change notification settings - Fork 40
Add ApptainerWorkspace implementation for rootless container support #892
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This commit implements ApptainerWorkspace, a container-based workspace that uses Apptainer (formerly Singularity) instead of Docker. This addresses the need for rootless container execution in HPC and shared computing environments where Docker may not be available or permitted. Key features: - No root privileges required for container execution - Converts Docker images to Apptainer SIF format with caching - Full RemoteWorkspace API compatibility - Automatic port management and health checking - Support for directory mounting and environment forwarding - Comprehensive documentation and examples Files added: - openhands-workspace/openhands/workspace/apptainer/workspace.py (implementation) - openhands-workspace/openhands/workspace/apptainer/__init__.py (module init) - openhands-workspace/openhands/workspace/apptainer/README.md (documentation) - examples/02_remote_agent_server/05_convo_with_apptainer_sandboxed_server.py (usage example) - tests/workspace/test_apptainer_workspace.py (test suite) - APPTAINER_WORKSPACE_TEST_LOG.md (test results and validation) Files modified: - openhands-workspace/openhands/workspace/__init__.py (export ApptainerWorkspace) Closes #891 Co-authored-by: openhands <[email protected]>
The ApptainerWorkspace implementation could not be tested end-to-end in the development environment because Apptainer is not installed. This commit adds transparency about testing limitations and provides clear guidance for users who want to test the implementation themselves. Changes: - Updated APPTAINER_WORKSPACE_TEST_LOG.md to explicitly state testing limitations - Added clear distinction between what was tested (code structure, types, API) and what requires Apptainer (runtime execution) - Added testing instructions to README.md for users with Apptainer installed - Clarified that validation focused on code correctness rather than runtime behavior This ensures users understand the implementation is structurally sound and type-correct, but requires Apptainer installation for full validation. Co-authored-by: openhands <[email protected]>
- Remove Docker dependency from _prepare_sif_image() - Use 'apptainer pull docker://image' instead of 'apptainer build ... docker-daemon://image' - This eliminates the need for Docker daemon, which is the main value of Apptainer - Remove unused imports (build, BuildOptions) - Add comprehensive test demonstrating Apptainer functionality - Successfully tested image pull and container execution - Document testing results and limitations Co-authored-by: openhands <[email protected]>
Co-authored-by: openhands <[email protected]>
- Switch ApptainerWorkspace from instance mode to exec mode for better compatibility - Fix RemoteWorkspace to include API key in default HTTP client headers - Add authentication support via SESSION_API_KEY environment variable - Include demo log showing successful Apptainer workspace operation Co-authored-by: openhands <[email protected]>
Coverage Report •
|
||||||||||||||||||||||||||||||
Keep only the essential implementation and demo log as requested in issue. Co-authored-by: openhands <[email protected]>
ℹ️ Note on
|
Co-authored-by: openhands <[email protected]>
- Fix missing dependency that caused import errors for openhands.agent_server modules - Add assertion for cache_dir to help type checking - This allows ApptainerWorkspace to correctly import BuildOptions and related classes Co-authored-by: openhands <[email protected]>
|
Looks like there are a few issues preventing this PR from being merged!
If you'd like me to help, just leave a comment, like Feel free to include any additional details that might help me get this PR into a better state. You can manage your notification settings |
|
[Automatic Post]: It has been a while since there was any activity on this PR. @neubig, are you still working on it? If so, please go ahead, if not then please request review, close it, or request that someone else follow up. |
Description
This PR implements
ApptainerWorkspace, a container-based workspace that uses Apptainer (formerly Singularity) instead of Docker. This addresses the need for rootless container execution in HPC and shared computing environments where Docker may not be available or permitted.✨ Critical Bug Fix (2025-10-24): Discovered and fixed a bug where the initial implementation incorrectly used
apptainer build ... docker-daemon://image, which required Docker to be running. This defeated the entire purpose of Apptainer! The fix changes toapptainer pull docker://imagewhich pulls directly from Docker registries without needing Docker daemon. This is the key feature that makes Apptainer valuable.✨ Additional Fixes (2025-10-24):
apptainer execfor better compatibility in environments without systemd/FUSESESSION_API_KEYfrom environment and passes it to RemoteWorkspaceFixes #891
Key Features
apptainer pullImplementation Details
Files Added
openhands-workspace/openhands/workspace/apptainer/workspace.py(378 lines)ApptainerWorkspaceclass implementationapptainer pull(no Docker required!)apptainer execopenhands-workspace/openhands/workspace/apptainer/__init__.pyopenhands-workspace/openhands/workspace/apptainer/README.mdexamples/02_remote_agent_server/05_convo_with_apptainer_sandboxed_server.pytests/workspace/test_apptainer_workspace.pyapptainer_workspace_demo.logFiles Modified
openhands-workspace/openhands/workspace/__init__.pyApptainerWorkspaceto exportsopenhands-workspace/openhands/workspace/apptainer/workspace.pyapptainer pullinstead of Docker daemonapptainer execinstead of instance mode for better compatibilityopenhands-sdk/openhands/sdk/workspace/remote/base.pyUsage
Option 1: Pre-built Server Image (Recommended for HPC)
Option 2: Build from Base Image (Requires Docker for initial build)
Option 3: Use Existing SIF File
Testing
All tests pass successfully:
$ uv run pytest tests/workspace/test_apptainer_workspace.py -v tests/workspace/test_apptainer_workspace.py::test_apptainer_workspace_import PASSED [ 33%] tests/workspace/test_apptainer_workspace.py::test_apptainer_workspace_inheritance PASSED [ 66%] tests/workspace/test_apptainer_workspace.py::test_apptainer_workspace_field_definitions PASSED [100%] ============================== 3 passed in 0.13s ===============================End-to-End Testing with Actual Apptainer
Successfully tested the complete example with Apptainer 1.3.5. See
apptainer_workspace_demo.logfor full details:✅ Image Preparation
/root/.apptainer_cache/ghcr.io_openhands_agent-server_main-python.sif✅ Container Execution
apptainer execmode✅ Command Execution
✅ Authentication
✅ API Endpoints
/healthendpoint: ✅ Working/api/bash/start_bash_command: ✅ Working/api/conversations: ✅ Working (with auth)/api/conversations/{id}/run: ✅ Working (with auth)All pre-commit hooks pass:
Comparison: ApptainerWorkspace vs DockerWorkspace
Prerequisites
Users need to install Apptainer: https://apptainer.org/docs/user/main/quick_start.html
On Ubuntu/Debian:
Or build from source:
Why Apptainer?
As mentioned in issue #891, Docker requires root access which is often not available or permitted in:
Apptainer was specifically designed for these use cases and provides:
Technical Implementation Notes
Exec Mode vs Instance Mode
Initially implemented using Apptainer instance mode (
apptainer instance start), but discovered this requires systemd and/or FUSE which may not be available in all environments. Switched to direct execution mode (apptainer exec) which:Authentication Flow
ApptainerWorkspace discovers SESSION_API_KEY from environment and passes it to RemoteWorkspace, which now properly includes it in the HTTP client's default headers. This ensures all API requests (including conversation creation) are properly authenticated.
Demo Log
See
apptainer_workspace_demo.logfor the complete end-to-end test output showing:Checklist
DockerWorkspaceNext Steps
After merging, users can:
ApptainerWorkspaceas a drop-in replacement forDockerWorkspaceAgent Server images for this PR
• GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server
Variants & Base Images
golang:1.21-bookwormeclipse-temurin:17-jdknikolaik/python-nodejs:python3.12-nodejs22Pull (multi-arch manifest)
Run
All tags pushed for this build
The
73648e4tag is a multi-arch manifest (amd64/arm64); your client pulls the right arch automatically.