I want to use Docker Remote API from Python Requests. It can be used from TCP if it is encrypted, but since we are thinking of using the API from the same host, we use unix socket.
The Docker socket file is in /var/run/docker.sock
. Reading and writing socket files is as follows.
import socket
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect("/var/run/docker.sock")
# s.recv, s.send, etc.
This is quite annoying and you need to implement Transport Adapter. And for that purpose, it is necessary to implement PoolManager, HTTPConnectionPool, and HTTPConnection together.
import socket
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3 import PoolManager, HTTPConnectionPool
from httplib import HTTPConnection
class MyAdapter(HTTPAdapter):
def __init__(self, sockfile, **kwargs):
self._sockfile = sockfile
super(MyAdapter, self).__init__(**kwargs)
def init_poolmanager(self, connections, maxsize, **kwargs):
self.poolmanager = MyPoolManager(self._sockfile,
num_pools=connections, maxsize=maxsize)
class MyPoolManager(PoolManager):
def __init__(self, sockfile, **kwargs):
self._sockfile = sockfile
super(MyPoolManager, self).__init__(**kwargs)
def _new_pool(self, scheme, host, port):
return MyConnectionPool(self._sockfile, host, port, **self.connection_pool_kw)
class MyConnectionPool(HTTPConnectionPool):
def __init__(self, sockfile, host, port, **kwargs):
self._sockfile = sockfile
super(MyConnectionPool, self).__init__(host, port, **kwargs)
def _new_conn(self):
self.num_connections += 1
return MyConnection(self._sockfile,
host=self.host, port=self.port, strict=self.strict)
class MyConnection(HTTPConnection):
def __init__(self, sockfile, **kwargs):
self._sockfile = sockfile
HTTPConnection.__init__(self, **kwargs)
def connect(self):
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self.sock.connect(self._sockfile)
if self._tunnel_host:
self._tunnel()
Note that HTTPConnection is an old-style class, so be careful about the initialization method.
The usage example is as follows.
req = requests.Session()
req.mount("http://", MyAdapter("/var/run/docker.sock"))
print req.get("http://127.0.0.1/images/json?all=0").json()
The place where it is written as http://127.0.0.1 is not good ...
Recommended Posts