wip docker module
This commit is contained in:
@@ -1,19 +1,30 @@
|
||||
from docker.models.containers import Container
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
import docker
|
||||
from docker.models.containers import Container
|
||||
import logging
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
class DockerModule:
|
||||
"""
|
||||
Module for handling Docker container operations in SIA.
|
||||
Manages container lifecycle, I/O operations, and status monitoring.
|
||||
"""
|
||||
|
||||
def _start_docker_engine():
|
||||
"""
|
||||
Start the Docker engine
|
||||
"""
|
||||
subprocess.run(['/etc/init.d/docker', 'start'])
|
||||
time.sleep(1)
|
||||
|
||||
def __init__(self):
|
||||
self.client = docker.from_env()
|
||||
DockerModule._start_docker_engine()
|
||||
self.client = docker.DockerClient(base_url='unix://var/run/docker.sock')
|
||||
self.containers: Dict[str, Container] = {}
|
||||
self.container_sockets: Dict[str, docker.APIClient.AttachSocket] = {}
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def start_container(
|
||||
self,
|
||||
image: str,
|
||||
@@ -69,7 +80,9 @@ class DockerModule:
|
||||
port_bindings[container_port] = host_port
|
||||
|
||||
try:
|
||||
container = self.client.containers.run(
|
||||
self.client.images.pull('busybox:latest')
|
||||
# Create container with tty and open stdin
|
||||
container = self.client.containers.create(
|
||||
image,
|
||||
command=cmd if cmd else None,
|
||||
name=name,
|
||||
@@ -77,21 +90,36 @@ class DockerModule:
|
||||
volumes=volume_binds,
|
||||
ports=port_bindings,
|
||||
environment=environment,
|
||||
tty=True,
|
||||
stdin_open=True
|
||||
)
|
||||
|
||||
# Attach socket before starting container
|
||||
socket = container.attach_socket(params={
|
||||
'stdin': 1,
|
||||
'stdout': 1,
|
||||
'stderr': 1,
|
||||
'stream': 1
|
||||
})
|
||||
|
||||
# Start the container
|
||||
container.start()
|
||||
|
||||
if timeout >= 0:
|
||||
# For short-lived containers, wait for completion
|
||||
try:
|
||||
container.wait(timeout=timeout/1000) # Convert ms to seconds
|
||||
output = container.logs().decode('utf-8')
|
||||
socket.close()
|
||||
container.remove(force=True)
|
||||
return output
|
||||
except docker.errors.NotFound:
|
||||
self.logger.warning(f"Container was removed before timeout")
|
||||
return ""
|
||||
else:
|
||||
# For long-running containers, store reference
|
||||
# For long-running containers, store references
|
||||
self.containers[name] = container
|
||||
self.container_sockets[name] = socket
|
||||
return name
|
||||
|
||||
except Exception as e:
|
||||
@@ -112,6 +140,12 @@ class DockerModule:
|
||||
raise KeyError(f"Container {name} not found")
|
||||
|
||||
try:
|
||||
# Close socket if it exists
|
||||
if name in self.container_sockets:
|
||||
self.container_sockets[name].close()
|
||||
del self.container_sockets[name]
|
||||
|
||||
# Stop and remove container
|
||||
container = self.containers[name]
|
||||
container.stop()
|
||||
container.remove()
|
||||
@@ -131,14 +165,12 @@ class DockerModule:
|
||||
KeyError: If container name not found
|
||||
docker.errors.APIError: If write operation fails
|
||||
"""
|
||||
if name not in self.containers:
|
||||
raise KeyError(f"Container {name} not found")
|
||||
if name not in self.containers or name not in self.container_sockets:
|
||||
raise KeyError(f"Container {name} not found or socket not initialized")
|
||||
|
||||
try:
|
||||
container = self.containers[name]
|
||||
socket = container.attach_socket(params={'stdin': 1, 'stream': 1})
|
||||
socket = self.container_sockets[name]
|
||||
socket._sock.send(data.encode('utf-8'))
|
||||
socket.close()
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error writing to container {name} stdin: {str(e)}")
|
||||
raise
|
||||
@@ -251,4 +283,4 @@ class DockerModule:
|
||||
}
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error getting status for container {name}: {str(e)}")
|
||||
raise
|
||||
raise
|
||||
|
||||
Reference in New Issue
Block a user