LoginSignup
2
2

More than 5 years have passed since last update.

Requests で Docker Remote API にアクセスする

Posted at

概要

Python Requests から Docker Remote API を利用したい.暗号化を行えば TCP からでも利用できるが,API を同じホストから利用することを考えているため unix ソケットを使う.

Unix ソケットの読み書き

Docker のソケットファイルは /var/run/docker.sock にある.ソケットファイルの読み書きは,次の通り.

import socket
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect("/var/run/docker.sock")
# s.recv, s.send, etc.

Requests で独自ソケットを使う

こちらはかなり面倒で,Transport Adapterを実装する必要がある.そして,そのためには,PoolManager,HTTPConnectionPool,HTTPConnection も合わせて実装する必要がある.

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()

HTTPConnection は old-style クラスなので,初期化方法に注意.

API の利用

利用例は次の通り.

req = requests.Session()
req.mount("http://", MyAdapter("/var/run/docker.sock"))
print req.get("http://127.0.0.1/images/json?all=0").json()

http://127.0.0.1 と書いているところがダサい・・・.

参考

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2