57 lines
1.6 KiB
Python
57 lines
1.6 KiB
Python
from __future__ import annotations
|
||
|
||
from typing import Dict, List, Optional
|
||
from pathlib import Path
|
||
import docker
|
||
|
||
from ..core.config import settings
|
||
|
||
|
||
class DockerRunner:
|
||
"""通过 docker.sock 在宿主机运行容器的轻量封装。"""
|
||
|
||
def __init__(self) -> None:
|
||
# 依赖 /var/run/docker.sock 已在 docker-compose 挂载至 worker 容器
|
||
self.client = docker.from_env()
|
||
|
||
def run(
|
||
self,
|
||
image: Optional[str],
|
||
command: List[str],
|
||
workdir: Path,
|
||
mounts: Dict[Path, str],
|
||
env: Optional[Dict[str, str]] = None,
|
||
platform: Optional[str] = None,
|
||
detach: bool = False,
|
||
remove: bool = True,
|
||
) -> str:
|
||
"""
|
||
运行容器并返回容器日志(非 detach)或容器 ID(detach)。
|
||
|
||
mounts: {host_path: container_path}
|
||
"""
|
||
image_to_use = image or settings.DOCKER_IMAGE
|
||
platform_to_use = platform or settings.DOCKER_PLATFORM
|
||
|
||
volumes = {str(host): {"bind": container, "mode": "rw"} for host, container in mounts.items()}
|
||
|
||
container = self.client.containers.run(
|
||
image=image_to_use,
|
||
command=command,
|
||
working_dir=str(workdir),
|
||
volumes=volumes,
|
||
environment=env or {},
|
||
platform=platform_to_use,
|
||
detach=detach,
|
||
remove=remove if not detach else False,
|
||
)
|
||
|
||
if detach:
|
||
return container.id
|
||
|
||
# 同步模式:等待并返回日志
|
||
result_bytes = container.logs(stream=False)
|
||
return result_bytes.decode("utf-8", errors="ignore")
|
||
|
||
|