r"""Build the Docker container and start it. Args: time_out (int): The number of seconds to wait for the container to start. (default: :obj: `15`) Returns: DockerRuntime: The DockerRuntime instance.
(self, time_out: int = 15)
| 166 | return self.container.exec_run(**task.model_dump()) |
| 167 | |
| 168 | def build(self, time_out: int = 15) -> "DockerRuntime": |
| 169 | r"""Build the Docker container and start it. |
| 170 | |
| 171 | Args: |
| 172 | time_out (int): The number of seconds to wait for the container to |
| 173 | start. (default: :obj: `15`) |
| 174 | |
| 175 | Returns: |
| 176 | DockerRuntime: The DockerRuntime instance. |
| 177 | """ |
| 178 | if self.container: |
| 179 | logger.warning("Container already exists. Nothing to build.") |
| 180 | return self |
| 181 | |
| 182 | import docker |
| 183 | from docker.types import Mount |
| 184 | |
| 185 | mounts = [] |
| 186 | for local_path, mount_path in self.mounts.items(): |
| 187 | mounts.append( |
| 188 | Mount( |
| 189 | target=str(mount_path), source=str(local_path), type="bind" |
| 190 | ) |
| 191 | ) |
| 192 | |
| 193 | container_params = { |
| 194 | "image": self.image, |
| 195 | "detach": True, |
| 196 | "mounts": mounts, |
| 197 | "command": "sleep infinity", |
| 198 | **self.docker_config, |
| 199 | } |
| 200 | container_params["ports"] = {"8000/tcp": self.port} |
| 201 | try: |
| 202 | self.container = self.client.containers.create(**container_params) |
| 203 | except docker.errors.APIError as e: |
| 204 | raise RuntimeError(f"Failed to create container: {e!s}") |
| 205 | |
| 206 | try: |
| 207 | self.container.start() |
| 208 | # Wait for the container to start |
| 209 | for _ in range(time_out): |
| 210 | self.container.reload() |
| 211 | logger.debug(f"Container status: {self.container.status}") |
| 212 | if self.container.status == "running": |
| 213 | break |
| 214 | time.sleep(1) |
| 215 | |
| 216 | except docker.errors.APIError as e: |
| 217 | raise RuntimeError(f"Failed to start container: {e!s}") |
| 218 | |
| 219 | # Copy files to the container if specified |
| 220 | for local_path, container_path in self.cp.items(): |
| 221 | logger.info(f"Copying {local_path} to {container_path}") |
| 222 | try: |
| 223 | with io.BytesIO() as tar_stream: |
| 224 | with tarfile.open(fileobj=tar_stream, mode="w") as tar: |
| 225 | tar.add( |