90 lines
2.8 KiB
Python
90 lines
2.8 KiB
Python
![]() |
import docker
|
|||
|
import os
|
|||
|
import logging
|
|||
|
from collections import deque
|
|||
|
|
|||
|
|
|||
|
class DockerRunner:
|
|||
|
def __init__(self, project_path: str):
|
|||
|
"""
|
|||
|
初始化 DockerRunner
|
|||
|
|
|||
|
Args:
|
|||
|
project_path (str): 项目路径,将挂载到 Docker 容器中
|
|||
|
"""
|
|||
|
self.project_path = project_path
|
|||
|
self.logger = logging.getLogger("DockerRunner")
|
|||
|
self.docker_client = docker.from_env()
|
|||
|
|
|||
|
def run_odm_container(self):
|
|||
|
"""
|
|||
|
使用 Docker SDK 运行 OpenDroneMap 容器
|
|||
|
"""
|
|||
|
try:
|
|||
|
self.logger.info("开始运行docker run指令")
|
|||
|
# 挂载路径
|
|||
|
volume_mapping = {
|
|||
|
self.project_path: {
|
|||
|
'bind': '/datasets',
|
|||
|
'mode': 'rw'
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
# Docker 命令参数
|
|||
|
command = [
|
|||
|
"--project-path", "/datasets",
|
|||
|
"project",
|
|||
|
"--max-concurrency", "15",
|
|||
|
"--force-gps",
|
|||
|
"--split-overlap", "0",
|
|||
|
]
|
|||
|
|
|||
|
# 运行容器
|
|||
|
container = self.docker_client.containers.run(
|
|||
|
image="opendronemap/odm:gpu",
|
|||
|
command=command,
|
|||
|
volumes=volume_mapping,
|
|||
|
device_requests=[
|
|||
|
docker.types.DeviceRequest(
|
|||
|
count=-1, capabilities=[["gpu"]])
|
|||
|
], # 添加 GPU 支持
|
|||
|
remove=False, # 容器运行结束后不自动删除,便于获取日志
|
|||
|
tty=True,
|
|||
|
detach=True # 后台运行
|
|||
|
)
|
|||
|
|
|||
|
# 等待容器运行完成
|
|||
|
exit_status = container.wait()
|
|||
|
if exit_status["StatusCode"] != 0:
|
|||
|
self.logger.error(f"容器运行失败,退出状态码: {exit_status['StatusCode']}")
|
|||
|
|
|||
|
# 获取容器的错误日志
|
|||
|
error_logs = container.logs(
|
|||
|
stderr=True).decode("utf-8").splitlines()
|
|||
|
self.logger.error("容器运行失败的详细错误日志:")
|
|||
|
for line in error_logs:
|
|||
|
self.logger.error(line)
|
|||
|
|
|||
|
else:
|
|||
|
# 获取所有日志
|
|||
|
logs = container.logs().decode("utf-8").splitlines()
|
|||
|
|
|||
|
# 输出最后 50 行日志
|
|||
|
self.logger.info("容器运行完成,以下是最后 50 行日志:")
|
|||
|
for line in logs[-50:]:
|
|||
|
self.logger.info(line)
|
|||
|
|
|||
|
# 删除容器
|
|||
|
container.remove()
|
|||
|
|
|||
|
except Exception as e:
|
|||
|
self.logger.error(f"运行 Docker 容器时发生错误: {str(e)}", exc_info=True)
|
|||
|
raise
|
|||
|
|
|||
|
|
|||
|
if __name__ == "__main__":
|
|||
|
# 示例用法
|
|||
|
project_path = r"E:\datasets\UAV\199"
|
|||
|
docker_runner = DockerRunner(project_path)
|
|||
|
docker_runner.run_odm_container()
|