Spaces:
Sleeping
Sleeping
| import docker | |
| from docker.errors import DockerException, ImageNotFound | |
| import logging | |
| from pathlib import Path | |
| logger = logging.getLogger(__name__) | |
| class ContainerBuilder: | |
| """Builds and manages the development environment Docker image""" | |
| IMAGE_NAME = "sandbox-devenv" | |
| IMAGE_TAG = "latest" | |
| def __init__(self): | |
| try: | |
| self.client = docker.from_env() | |
| logger.info("Container builder initialized") | |
| except DockerException as e: | |
| logger.error(f"Failed to initialize Docker client: {e}") | |
| raise RuntimeError("Docker is not available") from e | |
| def image_exists(self) -> bool: | |
| """Check if devenv image exists""" | |
| try: | |
| self.client.images.get(f"{self.IMAGE_NAME}:{self.IMAGE_TAG}") | |
| return True | |
| except ImageNotFound: | |
| return False | |
| def build_devenv_image(self) -> bool: | |
| """ | |
| Build the development environment image. | |
| Returns: | |
| True if successful, False otherwise | |
| """ | |
| try: | |
| dockerfile_path = Path(__file__).parent / "images" / "devenv.Dockerfile" | |
| if not dockerfile_path.exists(): | |
| logger.error(f"Dockerfile not found: {dockerfile_path}") | |
| return False | |
| logger.info("Building development environment image (this may take several minutes)...") | |
| # Build image | |
| image, build_logs = self.client.images.build( | |
| path=str(dockerfile_path.parent), | |
| dockerfile=str(dockerfile_path.name), | |
| tag=f"{self.IMAGE_NAME}:{self.IMAGE_TAG}", | |
| rm=True, # Remove intermediate containers | |
| pull=True, # Pull base image | |
| decode=True # Decode build logs | |
| ) | |
| # Print build progress | |
| for log in build_logs: | |
| if 'stream' in log: | |
| print(log['stream'], end='') | |
| elif 'error' in log: | |
| logger.error(f"Build error: {log['error']}") | |
| return False | |
| logger.info(f"Successfully built {self.IMAGE_NAME}:{self.IMAGE_TAG}") | |
| return True | |
| except Exception as e: | |
| logger.error(f"Failed to build image: {e}", exc_info=True) | |
| return False | |
| def ensure_devenv_image(self) -> bool: | |
| """ | |
| Ensure devenv image exists, build if necessary. | |
| Returns: | |
| True if image is available, False otherwise | |
| """ | |
| if self.image_exists(): | |
| logger.info(f"Image {self.IMAGE_NAME}:{self.IMAGE_TAG} already exists") | |
| return True | |
| logger.info(f"Image {self.IMAGE_NAME}:{self.IMAGE_TAG} not found, building...") | |
| return self.build_devenv_image() | |