-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathdocker.py
More file actions
115 lines (95 loc) · 2.86 KB
/
docker.py
File metadata and controls
115 lines (95 loc) · 2.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import os
import subprocess
import sys
from pathlib import Path
from typing import Tuple
import docker
from golem_task_api import constants, TaskApiService
def is_docker_available():
try:
docker.from_env().ping()
except Exception: # pylint: disable=broad-except
return False
return True
def run_docker_container(
image: str,
work_dir: Path,
command: str,
port: int
):
if sys.platform == 'linux':
ports = {}
else:
ports = {port: port}
docker_client = docker.from_env()
return docker_client.containers.run(
image=image,
command=command,
volumes={
str(work_dir): {
'bind': f'/{constants.WORK_DIR}',
'mode': 'rw',
}
},
user=os.getuid(),
ports=ports,
detach=True,
)
def get_docker_container_port_mapping(
container_id: str,
port: int,
vm_name: str = 'default',
) -> Tuple[str, int]:
api_client = docker.APIClient()
container_config = api_client.inspect_container(container_id)
net_config = container_config['NetworkSettings']
if sys.platform == 'darwin':
ip_address = '127.0.0.1'
port = int(net_config['Ports'][f'{port}/tcp'][0]['HostPort'])
elif sys.platform == 'win32':
ip_address = subprocess.check_output(['docker-machine', 'ip', vm_name])
ip_address = ip_address.decode('utf-8').strip()
port = int(net_config['Ports'][f'{port}/tcp'][0]['HostPort'])
else:
ip_address = net_config['Networks']['bridge']['IPAddress']
if not ip_address:
raise RuntimeError(f'Unable to read the IP address of {container_id}')
return ip_address, port
class DockerTaskApiService(TaskApiService):
def __init__(
self,
image: str,
work_dir: Path
) -> None:
self._image = image
self._work_dir = work_dir
self._container = None
async def start(
self,
command: str,
port: int
) -> Tuple[str, int]:
self._container = run_docker_container(
self._image,
self._work_dir,
command,
port)
return get_docker_container_port_mapping(self._container.id, port)
async def stop(self) -> None:
if not self.running():
return
self._container.stop()
def running(self) -> bool:
try:
self._container.reload()
except docker.errors.NotFound:
return False
return self._container.status not in ['exited', 'error']
async def wait_until_shutdown_complete(self) -> None:
if not self.running():
return
logs = self._container.logs().decode('utf-8')
try:
self._container.remove(force=True)
finally:
print(logs)