Skip to content

Commit 2a37f54

Browse files
committed
Add support windows
1 parent be3bf33 commit 2a37f54

File tree

4 files changed

+92
-11
lines changed

4 files changed

+92
-11
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@ Connect to remote docker (wia context or manual `--host` / `env DOCKER_HOST`), g
99
Supported OS:
1010
- Macos
1111
- Linux
12+
- Windows (needed cli docker.exe)
1213

1314
# Using
1415

15-
1. Install python 3
16+
1. Install python 3.8 (minimal version)
1617
2. Install requirements (`pip install -r requirements.txt`)
1718
3. Set docker host:
1819
* Configure via cli: `docker context`
1920
* Configure via env variable: `export DOCKER_HOST="ssh://user@remote-docker"`
2021
* Run with args `--host "ssh://user@remote-docker"`
2122
4. If needed listen privileged ports ( < 1024), add arg `--listen-system-ports`
22-
5. Run: `python src/main.py`
23+
5. If you want to interact via docker cli, add arg `--use-docker-cli`
24+
6. Run: `python src/main.py`

src/docker_cli_wrapper.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import subprocess, json
2+
3+
class DockerCLIWrapper(object):
4+
def containers(self, all=False):
5+
ps_args = ['docker', 'ps', '--format', '"{{json .}}"', '--no-trunc']
6+
if all:
7+
ps_args.append('-a')
8+
ps = subprocess.run(ps_args, capture_output=True)
9+
ps_output_jsonl = ps.stdout.decode().split("\n")
10+
containers = []
11+
for container_json in ps_output_jsonl:
12+
containers.append(DockerCliWrappedContainer(container_json))
13+
14+
return containers
15+
16+
def info(self):
17+
info_args = ['docker', 'info', '--format', '"{{json .}}"']
18+
info = subprocess.run(info_args, capture_output=True)
19+
return json.loads(info.stdout.decode()[1:-2])
20+
21+
22+
class DockerCliWrappedContainer(object):
23+
id = None
24+
image = None
25+
command = None
26+
createdAt = None
27+
labels = None
28+
names = None
29+
networks = None
30+
ports = None
31+
runningFor = None
32+
state = None
33+
status = None
34+
def __init__(self, jsonl):
35+
if len(jsonl) <= 2:
36+
return
37+
self.raw = json.loads(jsonl[1:-1])
38+
self.id = self.raw["ID"]
39+
self.image = self.raw["Image"]
40+
self.command = self.raw["Command"]
41+
self.createdAt = self.raw["CreatedAt"]
42+
self.labels = self.__parseLabels(self.raw["Labels"])
43+
self.ports = self.__parsePorts(self.raw["Ports"])
44+
self.networks = self.__parseNetworks(self.raw["Networks"])
45+
self.runningFor = self.raw["RunningFor"]
46+
self.state = self.raw["State"]
47+
self.status = self.raw["Status"]
48+
49+
def __parseLabels(self, raw_json):
50+
labels = {}
51+
for label_str in raw_json.split(","):
52+
label = label_str.split("=")
53+
labels[label[0]] = label[1] if len(label) > 1 else ""
54+
return labels
55+
56+
def __parsePorts(self, raw_json):
57+
if len(raw_json) == 0:
58+
return {}
59+
ports = {}
60+
for port_str in raw_json.split(", "):
61+
if port_str.find("->") == -1:
62+
ports[port_str] =[{"HostPort": port_str.replace("/tcp","").replace("/udp", "")}]
63+
else:
64+
port = port_str.replace("0.0.0.0:", "").split("->")
65+
ports[port[1]] = [{"HostPort":port[0]}]
66+
return ports
67+
68+
def __parseNetworks(self, raw_json):
69+
if len(raw_json) == 0:
70+
return []
71+
return raw_json.split(",")

src/docker_service.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,29 @@
22
import logging
33
import os
44
from urllib import parse
5+
from docker_cli_wrapper import DockerCliWrappedContainer, DockerCLIWrapper
56

67
class DockerService(object):
7-
def __init__(self, docker_host = None):
8+
def __init__(self, docker_host = None, use_cli = False):
89
self.docker_host = docker_host
9-
self.docker_client = docker.DockerClient(base_url=docker_host, use_ssh_client=docker_host.startswith("ssh"))
10+
if use_cli or os.name == "nt":
11+
self.docker_client = DockerCLIWrapper()
12+
self.use_cli = True
13+
else:
14+
self.docker_client = docker.DockerClient(base_url=docker_host, use_ssh_client=True)
15+
self.use_cli = False
1016
self.nodeInfo = self.docker_client.info()
1117
self.logger = logging.getLogger("DockerService")
1218

1319
def getRemoteHost(self):
1420
return parse.urlparse(os.getenv("DOCKER_HOST") if self.docker_host == None else self.docker_host).hostname
1521

1622
def getPublishedPorts(self):
17-
containers = self.docker_client.containers.list()
23+
containers = self.docker_client.containers.list() if not self.use_cli else self.docker_client.containers()
1824
ports = []
1925
for container in containers:
26+
if container.ports == None:
27+
continue
2028
for port in container.ports:
2129
if container.ports[port] == None:
2230
continue

src/main.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import json
55
import logging
66
import os
7-
import sys
87
import time
98
import argparse
109

@@ -45,10 +44,10 @@ def manageProxies(remote_docker_host_name, published_ports, listen_system_ports)
4544

4645

4746

48-
def mainLoop(docker_host, listen_system_ports):
47+
def mainLoop(docker_host, listen_system_ports, use_docker_cli):
4948
global ACTIVE_PROXIES
5049
logging.info("Initialize docker remote proxy to `%s`" %docker_host)
51-
docker_service = DockerService(docker_host)
50+
docker_service = DockerService(docker_host, use_docker_cli)
5251
remote_docker_host_name = docker_service.getRemoteHost()
5352

5453
try:
@@ -69,11 +68,12 @@ def mainLoop(docker_host, listen_system_ports):
6968
logging.info('Starting docker remote proxy!')
7069
parser = argparse.ArgumentParser(description='Remote docker context proxy')
7170
parser.add_argument('--listen-system-ports', action='store_true', help='Listen and Proxy system ports example: 22, 80, 443 etc.!')
71+
parser.add_argument('--use-docker-cli', action='store_true', help='Use docker cli instead of python docker client')
7272
parser.add_argument('--host', type=str, default=None, help='Docker host uri')
7373
args = parser.parse_args()
7474
if DOCKER_HOST_ENV != None:
75-
mainLoop(DOCKER_HOST_ENV, args.listen_system_ports)
75+
mainLoop(DOCKER_HOST_ENV, args.listen_system_ports, args.use_docker_cli)
7676
elif args.host != None:
77-
mainLoop(args.host, args.listen_system_ports)
77+
mainLoop(args.host, args.listen_system_ports, args.use_docker_cli)
7878
else:
79-
mainLoop(getDockerHostFromContext(), args.listen_system_ports)
79+
mainLoop(getDockerHostFromContext(), args.listen_system_ports, args.use_docker_cli)

0 commit comments

Comments
 (0)