mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
Update docker.py to support podman (#6778)
This commit is contained in:
parent
2db7a50e43
commit
78cc27a18f
@ -19,19 +19,25 @@ class DockerRuntimeBuilder(RuntimeBuilder):
|
||||
|
||||
version_info = self.docker_client.version()
|
||||
server_version = version_info.get('Version', '').replace('-', '.')
|
||||
if tuple(map(int, server_version.split('.')[:2])) < (18, 9):
|
||||
self.is_podman = version_info.get('Components')[0].get('Name').startswith('Podman')
|
||||
if tuple(map(int, server_version.split('.')[:2])) < (18, 9) and not self.is_podman:
|
||||
raise AgentRuntimeBuildError(
|
||||
'Docker server version must be >= 18.09 to use BuildKit'
|
||||
)
|
||||
|
||||
if self.is_podman and tuple(map(int, server_version.split('.')[:2])) < (4, 9):
|
||||
raise AgentRuntimeBuildError(
|
||||
'Podman server version must be >= 4.9.0'
|
||||
)
|
||||
|
||||
self.rolling_logger = RollingLogger(max_lines=10)
|
||||
|
||||
@staticmethod
|
||||
def check_buildx():
|
||||
def check_buildx(is_podman: bool = False):
|
||||
"""Check if Docker Buildx is available"""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
['docker', 'buildx', 'version'], capture_output=True, text=True
|
||||
['docker' if not is_podman else 'podman', 'buildx', 'version'], capture_output=True, text=True
|
||||
)
|
||||
return result.returncode == 0
|
||||
except FileNotFoundError:
|
||||
@ -68,12 +74,18 @@ class DockerRuntimeBuilder(RuntimeBuilder):
|
||||
self.docker_client = docker.from_env()
|
||||
version_info = self.docker_client.version()
|
||||
server_version = version_info.get('Version', '').split('+')[0].replace('-', '.')
|
||||
if tuple(map(int, server_version.split('.'))) < (18, 9):
|
||||
self.is_podman = version_info.get('Components')[0].get('Name').startswith('Podman')
|
||||
if tuple(map(int, server_version.split('.'))) < (18, 9) and not self.is_podman:
|
||||
raise AgentRuntimeBuildError(
|
||||
'Docker server version must be >= 18.09 to use BuildKit'
|
||||
)
|
||||
|
||||
if not DockerRuntimeBuilder.check_buildx():
|
||||
if self.is_podman and tuple(map(int, server_version.split('.'))) < (4, 9):
|
||||
raise AgentRuntimeBuildError(
|
||||
'Podman server version must be >= 4.9.0'
|
||||
)
|
||||
|
||||
if not DockerRuntimeBuilder.check_buildx(self.is_podman):
|
||||
# when running openhands in a container, there might not be a "docker"
|
||||
# binary available, in which case we need to download docker binary.
|
||||
# since the official openhands app image is built from debian, we use
|
||||
@ -110,7 +122,7 @@ class DockerRuntimeBuilder(RuntimeBuilder):
|
||||
target_image_tag = tags[1].split(':')[1] if len(tags) > 1 else None
|
||||
|
||||
buildx_cmd = [
|
||||
'docker',
|
||||
'docker' if not self.is_podman else 'podman',
|
||||
'buildx',
|
||||
'build',
|
||||
'--progress=plain',
|
||||
@ -139,7 +151,7 @@ class DockerRuntimeBuilder(RuntimeBuilder):
|
||||
buildx_cmd.append(path) # must be last!
|
||||
|
||||
self.rolling_logger.start(
|
||||
'================ DOCKER BUILD STARTED ================'
|
||||
f'================ {buildx_cmd[0].upper()} BUILD STARTED ================'
|
||||
)
|
||||
|
||||
try:
|
||||
|
||||
@ -21,7 +21,10 @@ def mock_docker_client():
|
||||
mock_client.return_value.containers.get.return_value = container_mock
|
||||
mock_client.return_value.containers.run.return_value = container_mock
|
||||
# Mock version info for BuildKit check
|
||||
mock_client.return_value.version.return_value = {'Version': '20.10.0'}
|
||||
mock_client.return_value.version.return_value = {
|
||||
'Version': '20.10.0',
|
||||
'Components': [{'Name': 'Engine', 'Version': '20.10.0'}],
|
||||
} # Ensure version is >= 18.09
|
||||
yield mock_client.return_value
|
||||
|
||||
|
||||
|
||||
@ -40,7 +40,8 @@ def temp_dir(tmp_path_factory: TempPathFactory) -> str:
|
||||
def mock_docker_client():
|
||||
mock_client = MagicMock(spec=docker.DockerClient)
|
||||
mock_client.version.return_value = {
|
||||
'Version': '19.03'
|
||||
'Version': '20.10.0',
|
||||
'Components': [{'Name': 'Engine', 'Version': '20.10.0'}],
|
||||
} # Ensure version is >= 18.09
|
||||
return mock_client
|
||||
|
||||
@ -612,7 +613,10 @@ CMD ["sh", "-c", "echo 'Hello, World!'"]
|
||||
|
||||
def test_image_exists_local(docker_runtime_builder):
|
||||
mock_client = MagicMock()
|
||||
mock_client.version().get.return_value = '18.9'
|
||||
mock_client.version.return_value = {
|
||||
'Version': '20.10.0',
|
||||
'Components': [{'Name': 'Engine', 'Version': '20.10.0'}],
|
||||
} # Ensure version is >= 18.09
|
||||
builder = DockerRuntimeBuilder(mock_client)
|
||||
image_name = 'existing-local:image' # The mock pretends this exists by default
|
||||
assert builder.image_exists(image_name)
|
||||
@ -620,7 +624,10 @@ def test_image_exists_local(docker_runtime_builder):
|
||||
|
||||
def test_image_exists_not_found():
|
||||
mock_client = MagicMock()
|
||||
mock_client.version().get.return_value = '18.9'
|
||||
mock_client.version.return_value = {
|
||||
'Version': '20.10.0',
|
||||
'Components': [{'Name': 'Engine', 'Version': '20.10.0'}],
|
||||
} # Ensure version is >= 18.09
|
||||
mock_client.images.get.side_effect = docker.errors.ImageNotFound(
|
||||
"He doesn't like you!"
|
||||
)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user