feat(sandbox): add support for extra Docker build arguments (#5447)

This commit is contained in:
Cheng Yang 2024-12-12 10:21:46 +08:00 committed by GitHub
parent ffd472d6b8
commit 7e4c1c733b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 30 additions and 3 deletions

View File

@ -217,6 +217,9 @@ llm_config = 'gpt3'
# Use host network
#use_host_network = false
# runtime extra build args
#runtime_extra_build_args = ["--network=host", "--add-host=host.docker.internal:host-gateway"]
# Enable auto linting after editing
#enable_auto_lint = false

View File

@ -48,6 +48,7 @@ class SandboxConfig:
False # once enabled, OpenHands would lint files after editing
)
use_host_network: bool = False
runtime_extra_build_args: list[str] | None = None
initialize_plugins: bool = True
force_rebuild_runtime: bool = False
runtime_extra_deps: str | None = None

View File

@ -8,6 +8,7 @@ class RuntimeBuilder(abc.ABC):
path: str,
tags: list[str],
platform: str | None = None,
extra_build_args: list[str] | None = None,
) -> str:
"""Build the runtime image.
@ -15,6 +16,7 @@ class RuntimeBuilder(abc.ABC):
path (str): The path to the runtime image's build directory.
tags (list[str]): The tags to apply to the runtime image (e.g., ["repo:my-repo", "sha:my-sha"]).
platform (str, optional): The target platform for the build. Defaults to None.
extra_build_args (list[str], optional): Additional build arguments to pass to the builder. Defaults to None.
Returns:
str: The name:tag of the runtime image after build (e.g., "repo:sha").

View File

@ -28,8 +28,8 @@ class DockerRuntimeBuilder(RuntimeBuilder):
path: str,
tags: list[str],
platform: str | None = None,
use_local_cache: bool = False,
extra_build_args: list[str] | None = None,
use_local_cache: bool = False,
) -> str:
"""Builds a Docker image using BuildKit and handles the build logs appropriately.

View File

@ -23,7 +23,13 @@ class RemoteRuntimeBuilder(RuntimeBuilder):
self.session = requests.Session()
self.session.headers.update({'X-API-Key': self.api_key})
def build(self, path: str, tags: list[str], platform: str | None = None) -> str:
def build(
self,
path: str,
tags: list[str],
platform: str | None = None,
extra_build_args: list[str] | None = None,
) -> str:
"""Builds a Docker image using the Runtime API's /build endpoint."""
# Create a tar archive of the build context
tar_buffer = io.BytesIO()

View File

@ -229,6 +229,7 @@ class EventStreamRuntime(Runtime):
platform=self.config.sandbox.platform,
extra_deps=self.config.sandbox.runtime_extra_deps,
force_rebuild=self.config.sandbox.force_rebuild_runtime,
extra_build_args=self.config.sandbox.runtime_extra_build_args,
)
self.log(

View File

@ -111,6 +111,7 @@ def build_runtime_image(
build_folder: str | None = None,
dry_run: bool = False,
force_rebuild: bool = False,
extra_build_args: List[str] | None = None,
) -> str:
"""Prepares the final docker build folder.
If dry_run is False, it will also build the OpenHands runtime Docker image using the docker build folder.
@ -123,6 +124,7 @@ def build_runtime_image(
- build_folder (str): The directory to use for the build. If not provided a temporary directory will be used
- dry_run (bool): if True, it will only ready the build folder. It will not actually build the Docker image
- force_rebuild (bool): if True, it will create the Dockerfile which uses the base_image
- extra_build_args (List[str]): Additional build arguments to pass to the builder
Returns:
- str: <image_repo>:<MD5 hash>. Where MD5 hash is the hash of the docker build folder
@ -139,6 +141,7 @@ def build_runtime_image(
dry_run=dry_run,
force_rebuild=force_rebuild,
platform=platform,
extra_build_args=extra_build_args,
)
return result
@ -150,6 +153,7 @@ def build_runtime_image(
dry_run=dry_run,
force_rebuild=force_rebuild,
platform=platform,
extra_build_args=extra_build_args,
)
return result
@ -162,6 +166,7 @@ def build_runtime_image_in_folder(
dry_run: bool,
force_rebuild: bool,
platform: str | None = None,
extra_build_args: List[str] | None = None,
) -> str:
runtime_image_repo, _ = get_runtime_image_repo_and_tag(base_image)
lock_tag = f'oh_v{oh_version}_{get_hash_for_lock_files(base_image)}'
@ -193,6 +198,7 @@ def build_runtime_image_in_folder(
lock_tag,
versioned_tag,
platform,
extra_build_args=extra_build_args,
)
return hash_image_name
@ -234,6 +240,7 @@ def build_runtime_image_in_folder(
if build_from == BuildFromImageType.SCRATCH
else None,
platform=platform,
extra_build_args=extra_build_args,
)
return hash_image_name
@ -339,6 +346,7 @@ def _build_sandbox_image(
lock_tag: str,
versioned_tag: str | None,
platform: str | None = None,
extra_build_args: List[str] | None = None,
):
"""Build and tag the sandbox image. The image will be tagged with all tags that do not yet exist"""
names = [
@ -350,7 +358,10 @@ def _build_sandbox_image(
names = [name for name in names if not runtime_builder.image_exists(name, False)]
image_name = runtime_builder.build(
path=str(build_folder), tags=names, platform=platform
path=str(build_folder),
tags=names,
platform=platform,
extra_build_args=extra_build_args,
)
if not image_name:
raise RuntimeError(f'Build failed for image {names}')

View File

@ -239,6 +239,7 @@ def test_build_runtime_image_from_scratch():
f'{get_runtime_image_repo()}:{OH_VERSION}_mock-versioned-tag',
],
platform=None,
extra_build_args=None,
)
assert (
image_name
@ -333,6 +334,7 @@ def test_build_runtime_image_exact_hash_not_exist_and_lock_exist():
# VERSION tag will NOT be included except from scratch
],
platform=None,
extra_build_args=None,
)
mock_prep_build_folder.assert_called_once_with(
ANY,
@ -391,6 +393,7 @@ def test_build_runtime_image_exact_hash_not_exist_and_lock_not_exist_and_version
# VERSION tag will NOT be included except from scratch
],
platform=None,
extra_build_args=None,
)
mock_prep_build_folder.assert_called_once_with(
ANY,