README.md
1 # Host Volume Mount Example 2 3 This example demonstrates how to mount host directories into sandbox containers using the OpenSandbox Volume API. Host volume mounts enable bidirectional file sharing between the host machine and sandbox environments — ideal for sharing datasets, model checkpoints, configuration files, or collecting sandbox outputs. 4 5 ## Scenarios 6 7 | # | Scenario | Description | 8 |---|----------|-------------| 9 | 1 | **Read-write mount** | Mount a host directory for bidirectional file exchange | 10 | 2 | **Read-only mount** | Provide shared data that sandboxes cannot modify | 11 | 3 | **SubPath mount** | Mount a specific subdirectory from the host path | 12 13 ## Prerequisites 14 15 ### 1. Start OpenSandbox Server 16 17 ```shell 18 git clone git@github.com:alibaba/OpenSandbox.git 19 cd OpenSandbox/server 20 cp opensandbox_server/examples/example.config.toml ~/.sandbox.toml 21 uv sync && uv run python -m opensandbox_server.main 22 ``` 23 24 ### 2. Configure Allowed Host Paths 25 26 For security, the server restricts which host paths can be mounted. Add a `[storage]` section to `~/.sandbox.toml`: 27 28 ```toml 29 [storage] 30 # Allowlist of host path prefixes permitted for bind mounts. 31 # Only paths under these prefixes can be mounted into sandboxes. 32 # If empty, all host paths are allowed (not recommended for production). 33 allowed_host_paths = ["/tmp/opensandbox-data", "/data/shared"] 34 ``` 35 36 > **Security note**: In production, always set explicit `allowed_host_paths` to prevent sandboxes from accessing sensitive host directories. An empty list allows all paths, which is convenient for local development but not safe for shared environments. 37 38 ### 3. Create Host Directories 39 40 ```shell 41 # Create a directory to share with sandboxes 42 mkdir -p /tmp/opensandbox-data 43 echo "hello-from-host" > /tmp/opensandbox-data/marker.txt 44 45 # Create a subdirectory for the subpath demo 46 mkdir -p /tmp/opensandbox-data/datasets/train 47 echo -e "id,value\n1,100\n2,200\n3,300" > /tmp/opensandbox-data/datasets/train/data.csv 48 ``` 49 50 ### 4. Install SDK from Source 51 52 Volume support requires the latest SDK built from source (not yet available in the released package): 53 54 ```shell 55 # From the project root (recommended: use uv) 56 uv pip install -e sdks/sandbox/python 57 58 # Or use pip inside a virtual environment 59 # python3 -m venv .venv && source .venv/bin/activate 60 # pip install -e sdks/sandbox/python 61 ``` 62 63 ### 5. Pull the Sandbox Image 64 65 ```shell 66 docker pull ubuntu:latest 67 ``` 68 69 ## Run 70 71 ```shell 72 HOST_VOLUME_PATH=/tmp/opensandbox-data uv run python examples/host-volume-mount/main.py 73 ``` 74 75 ## Expected Output 76 77 ```text 78 Using HOST_VOLUME_PATH: /tmp/opensandbox-data 79 80 OpenSandbox server : localhost:8080 81 Sandbox image : ubuntu 82 Host volume path : /tmp/opensandbox-data 83 84 ============================================================ 85 Scenario 1: Read-Write Host Volume Mount 86 ============================================================ 87 Host path : /tmp/opensandbox-data 88 Mount path: /mnt/shared 89 90 [1] Listing files visible from inside the sandbox: 91 total 12 92 drwxrwxrwx 3 root root 4096 ... . 93 drwxr-xr-x 1 root root 4096 ... .. 94 -rw-r--r-- 1 root root 16 ... marker.txt 95 drwxr-xr-x 3 root root 4096 ... datasets 96 97 [2] Writing a file from inside the sandbox: 98 -> Written: /mnt/shared/sandbox-greeting.txt 99 100 [3] Reading back the file: 101 Hello from sandbox! 102 103 [4] Verified on host: /tmp/opensandbox-data/sandbox-greeting.txt 104 Content: Hello from sandbox! 105 106 Scenario 1 completed. 107 108 ============================================================ 109 Scenario 2: Read-Only Host Volume Mount 110 ============================================================ 111 Host path : /tmp/opensandbox-data 112 Mount path: /mnt/readonly 113 114 [1] Reading files from read-only mount: 115 ... 116 117 [2] Reading marker.txt: 118 hello-from-host 119 120 [3] Attempting to write (should fail): 121 Write denied (expected) 122 123 Scenario 2 completed. 124 125 ============================================================ 126 Scenario 3: SubPath Host Volume Mount 127 ============================================================ 128 Host path : /tmp/opensandbox-data 129 SubPath : datasets/train 130 Mount path: /mnt/training-data 131 132 [1] Listing mounted subpath content: 133 ... 134 -rw-r--r-- 1 root root 28 ... data.csv 135 136 [2] Reading data.csv: 137 id,value 138 1,100 139 2,200 140 3,300 141 142 Scenario 3 completed. 143 144 ============================================================ 145 All scenarios completed successfully! 146 ============================================================ 147 ``` 148 149 ## SDK Usage Quick Reference 150 151 ### Python (async) 152 153 ```python 154 from opensandbox import Sandbox 155 from opensandbox.models.sandboxes import Host, Volume 156 157 sandbox = await Sandbox.create( 158 image="ubuntu", 159 volumes=[ 160 Volume( 161 name="my-data", 162 host=Host(path="/data/shared"), 163 mountPath="/mnt/data", 164 readOnly=False, # optional, default is False 165 subPath="subdir", # optional, mount a subdirectory 166 ), 167 ], 168 ) 169 ``` 170 171 ### Python (sync) 172 173 ```python 174 from opensandbox import SandboxSync 175 from opensandbox.models.sandboxes import Host, Volume 176 177 sandbox = SandboxSync.create( 178 image="ubuntu", 179 volumes=[ 180 Volume( 181 name="my-data", 182 host=Host(path="/data/shared"), 183 mountPath="/mnt/data", 184 ), 185 ], 186 ) 187 ``` 188 189 ### JavaScript / TypeScript 190 191 ```typescript 192 import { Sandbox } from "@alibaba-group/opensandbox"; 193 194 const sandbox = await Sandbox.create({ 195 image: "ubuntu", 196 volumes: [ 197 { 198 name: "my-data", 199 host: { path: "/data/shared" }, 200 mountPath: "/mnt/data", 201 readOnly: false, 202 }, 203 ], 204 }); 205 ``` 206 207 ### Java / Kotlin 208 209 ```java 210 Volume volume = Volume.builder() 211 .name("my-data") 212 .host(Host.of("/data/shared")) 213 .mountPath("/mnt/data") 214 .readOnly(false) 215 .build(); 216 217 Sandbox sandbox = Sandbox.builder() 218 .image("ubuntu") 219 .volume(volume) 220 .build(); 221 ``` 222 223 ## References 224 225 - [OSEP-0003: Volume and VolumeBinding Support](../../oseps/0003-volume-and-volumebinding-support.md) — Design proposal 226 - [Sandbox Lifecycle API Spec](../../specs/sandbox-lifecycle.yml) — OpenAPI schema for volume definitions 227 - [Server Configuration](../../server/example.config.toml) — `[storage]` section for `allowed_host_paths`