Python调用Docker API

调用方式

# api方式
data = {
	"base_url": "tcp://ip:port",
    "sign": "api",
    "apiversion": ""
}
# 实例化对象
tt = DockerManage(**data)

# ssh方式,必须指定apiversion版本号
data = {
	"base_url": "ssh://username:password@ip:port",
    "sign": "ssh",
    "apiversion": "1.23"
}
# 实例化对象
tt = DockerManage(**data)

# 获取容器所有列表
tt.ContainerList()

# 获取镜像列表
tt.Images()

# 拉取镜像
tt.pullimage(tag="镜像id或者镜像名称:镜像")

脚本内容

from io import BytesIO
import os
import docker
from docker import transport, DockerClient
from config import MIN_DOCKER_API, DEFAULT_NUM_POOLS, DEFAULT_MAX_POOL_SIZE

# docker 配置
MIN_DOCKER_API = "1.21"
DEFAULT_NUM_POOLS = 25
DEFAULT_MAX_POOL_SIZE = 30


class SSHHTTPAdapter(transport.SSHHTTPAdapter):
    def __init__(self, ssh_params, timeout=60, pool_connections=DEFAULT_NUM_POOLS,
                 max_pool_size=DEFAULT_MAX_POOL_SIZE, shell_out=False):
        self.ssh_params = ssh_params
        del ssh_params['scheme']
        super(SSHHTTPAdapter, self).__init__('', timeout, pool_connections, max_pool_size, shell_out)
    def _create_paramiko_client(self, _):
        # logging.getLogger("paramiko").setLevel(logging.WARNING)
        self.ssh_client = paramiko.SSHClient()
        ssh_config_file = os.path.expanduser("~/.ssh/config")
        if os.path.exists(ssh_config_file):
            conf = paramiko.SSHConfig()
            with open(ssh_config_file) as f:
                conf.parse(f)
            host_config = conf.lookup(self.ssh_params['hostname'])
            self.ssh_conf = host_config
            if 'proxycommand' in host_config:
                self.ssh_params["sock"] = paramiko.ProxyCommand(
                    self.ssh_conf['proxycommand']
                )
            if 'hostname' in host_config:
                self.ssh_params['hostname'] = host_config['hostname']
            if self.ssh_params['port'] is None and 'port' in host_config:
                self.ssh_params['port'] = self.ssh_conf['port']
            if self.ssh_params['username'] is None and 'user' in host_config:
                self.ssh_params['username'] = self.ssh_conf['user']

        self.ssh_client.load_system_host_keys()
        self.ssh_client.set_missing_host_key_policy(paramiko.WarningPolicy())


class SSHDockerClient(DockerClient):
    def __init__(self, *args, **kwargs):
        base_url = kwargs.get('base_url')
        ssh_params = docker_urlparse(base_url)
        adapter = SSHHTTPAdapter(ssh_params)
        kwargs['base_url'] = ''
        kwargs['version'] = kwargs.get('version')
        super(SSHDockerClient, self).__init__(*args, **kwargs)
        self.api.mount('http+docker://ssh', adapter)
        self.api.base_url = 'http+docker://ssh'


def docker_urlparse(url):
    # fix for url with '#'
    mark = '_a5s7m3_'
    r = urlparse(url.replace('#', mark))
    hostname = r.hostname.replace(mark, '#')
    username = r.username.replace(mark, '#')
    password = r.password.replace(mark, '#')
    port = r.port
    scheme = r.scheme
    return {
        'hostname': hostname,
        'port': port,
        'username': username,
        'password': decrypt(password[2:-1]),
        'scheme': scheme
    }


class DockerManage:
    def __init__(self, *args, **kwargs) -> None:
        self.base_url = kwargs.get("base_url")
        self.sign = kwargs.get("sign")
        self.apiversion = kwargs.get("apiversion")
        self.success_code = 200
        self.fail_code = 400
    
    # 初始化docker连接对象
    def Client(self):
        if self.sign == "api":
            docker_clinet = docker.DockerClient(base_url=self.base_url)
            return docker_clinet
        elif self.sign == "ssh":
            docker_clinet = SSHDockerClient(base_url=self.base_url,version=self.apiversion)
            return docker_clinet

    
    # 获取容器
    def ContainerList(self):
        try:
            client = self.Client()
            container_list = client.api.containers(all=True)
            client.close()
            containers = []
            if container_list:
                for container in container_list:
                    id = container["Id"]
                    names = container["Names"][0].split("/")[1]
                    image = container["Image"]
                    if container["Ports"]:
                        ports = []
                        for ptp in container["Ports"]:
                            if "PublicPort" in ptp.keys():
                                pstr = ptp["IP"] + ":" + str(ptp["PublicPort"]) + "->" + str(ptp["PrivatePort"])
                                ports.append(pstr)
                    else:
                        ports = container["Ports"]
                    status = container["State"]
                    created = TimeTool(container["Created"])
                    
                    if container["Mounts"]:
                        mount = []
                        for mtp in container["Mounts"]:
                            if mtp["Source"]:
                                mtp_str = mtp["Source"] + ":" + mtp["Destination"]
                                mount.append(mtp_str)
                    else:
                        mount = container["Mounts"]
                    container_dict = {"id": id, "name": names, "image": image, "ports": ports, "status": status, "mount": mount, "created": created}
                    containers.append(container_dict)
            return  {"code": self.success_code, "msg": "获取成功","data": containers}    
        except Exception as e:
            return  {"code": self.fail_code, "msg": "获取失败 %s" % str(e),"data": []}    
                

    # 返回本地镜像列表: 镜像tag 镜像大小 镜像创建时间
    def Images(self):
        try:
            client = self.Client()
            images = client.api.images(all=True)
            client.close()
            imagesRes = []
            for image in images:
                created = TimeTool(image["Created"])
                size = HumConvert(image["Size"])
                for tag in image["RepoTags"]:
                    imagesRes.append({"tag": tag, "size": size, "created": created})
            return {"code": self.success_code, "msg": "获取成功", "data": imagesRes}
        except Exception as e:
            return  {"code": self.fail_code, "msg": "获取失败 %s" % str(e),"data": []}    

    # 拉取镜像
    def pullimage(self, tag):
        try:
            client = self.Client()
            client.images.pull(repository=tag)
            client.close()
            return {"code": self.success_code, "msg": "拉取成功", "data": ""}
        except Exception as e:
            return  {"code": self.fail_code, "msg": "拉取失败: " ,"data": [e]}  

    # 删除镜像
    def DelImage(self,tag):
        try:
            client = self.Client()
            client.images.remove(image=tag)
            client.close()
            return {"code": self.success_code, "msg": "删除成功", "data": []}
        except Exception as e:
            return  {"code": self.fail_code, "msg": "删除失败: %s" % str(e),"data": []}  

    # 镜像搜索
    def SearchImg(self,tag):
        try:
            client = self.Client()
            res = client.images.search(tag)
            client.close()
            return {"code": self.success_code, "msg": "查询成功", "data": res}
        except Exception as e:
            return  {"code": self.fail_code, "msg": "查询失败: %s" % str(e),"data": []}  

    # 镜像历史
    def historyImg(self,tag):
        try:
            client = self.Client()
            res = client.api.history(tag)
            client.close()
            return {"code": self.success_code, "msg": "查询成功", "data": res}
        except Exception as e:
            return  {"code": self.fail_code, "msg": "查询失败: %s" % str(e),"data": []} 
    

    # 提交镜像
    def pushImg(self, repository):
        try:
            client = self.Client()
            res = client.api.push(repository=repository)
            client.close()
            return {"code": self.success_code, "msg": "提交成功", "data": res}
        except Exception as e:
            return  {"code": self.fail_code, "msg": "提交失败: %s" % str(e),"data": []}   

    # 重命名镜像
    def tagImg(self, image, repository):
        try:
            client = self.Client()
            res = client.api.tag(image=image, repository=repository)
            client.close()
            return {"code": self.success_code, "msg": "提交成功", "data": res}
        except Exception as e:
            return  {"code": self.fail_code, "msg": "提交失败: %s" % str(e),"data": []}  
    
    # 扩展提交镜像
    def extPush(self, image, repository):
        try:
            client = self.Client()
            res = client.api.tag(image=image, repository=repository)
            if res:
                pres = client.api.push(repository=repository)
                client.close()
                return {"code": self.success_code, "msg": "提交成功", "data": pres}
            else:
                return  {"code": self.fail_code, "msg": "提交失败: %s" % str(res),"data": []}  
        except Exception as e:
            return  {"code": self.fail_code, "msg": "提交失败: %s" % str(e),"data": []}  

    # 重命名容器
    def RenameContainers(self, oldname, newname):
        try:
            client = self.Client()
            client.api.rename(oldname, newname)
            client.close()
            return {"code": self.success_code, "msg": "重命名成功", "data": []}
        except Exception as e:
            return  {"code": self.fail_code, "msg": "重命名失败: %s" % str(e),"data": []}  

    # 重启容器
    def RestartContainers(self, id):
        try:
            client = self.Client()
            client.api.restart(id)
            client.close()
            return {"code": self.success_code, "msg": "重启成功", "data": []}
        except Exception as e:
            return  {"code": self.fail_code, "msg": "重启失败: %s" % str(e),"data": []}  

    # 启动容器
    def StartContainers(self, id):
        try:
            client = self.Client()
            client.api.start(id)
            client.close()
            return {"code": self.success_code, "msg": "启动成功", "data": []}
        except Exception as e:
            return  {"code": self.fail_code, "msg": "启动失败: %s" % str(e),"data": []}  
    
    # 停止容器
    def StopContainers(self, id):
        try:
            client = self.Client()
            client.api.stop(id)
            client.close()
            
            return {"code": self.success_code, "msg": "停止成功", "data": []}
        except Exception as e:
            return  {"code": self.fail_code, "msg": "停止失败: %s" % str(e),"data": []}  

    # 删除容器
    def RemoveContainers(self, id):
        try:
            stopRes = self.StopContainers(id)
            if stopRes["code"] == 200:
                client = self.Client()
                client.api.remove_container(id)
                client.close()
                return {"code": self.success_code, "msg": "删除成功", "data": []}
            else:
                return {"code": self.fail_code, "msg": "删除失败: %s" % stopRes['msg'],"data": []}  
        except Exception as e:
            return  {"code": self.fail_code, "msg": "删除失败: %s" % str(e),"data": []}  
    
    # 创建容器
    def RunContainers(self, data):
        try:
            client = self.Client()
            if ";" in data["binds"]:
                volumes = data["binds"].split(";")
            elif ":" in [data["binds"]]:
                volumes = [data["binds"]]
            else:
                volumes = []
            prots = {}
            if ";" in data["port_bindings"]:
                portLst = data["port_bindings"].split(";")
                prots = {}
                for port in portLst:
                    key = port.split(":")[1]
                    value = port.split(":")[0]
                    prots[key] = value
            elif data["port_bindings"]:
                key = data["port_bindings"].split(":")[1]
                value = data["port_bindings"].split(":")[0]
                prots[key] = value
            if data["nano_cpus"]:
                nano_cpus = int(data["nano_cpus"]) * 1000000000
            else:
                nano_cpus = ""
            
            if ";" in data["environment"]:
                environment = data["environment"].split(";")
            elif ":" in data["environment"]:
                environment = [data["environment"]]
            else:
                environment = []

            container = client.containers.create(
                image=data["image"],
                environment=environment,
                hostname=data["hostname"],
                name=data["name"],
                nano_cpus=nano_cpus,
                mem_limit=data["mem_limit"],
                network=data["network"],
                volumes=volumes,
                ports=prots,
                detach=True,
                network_mode=data["network_mode"],
                restart_policy=data["restart_policy"],
                shm_size=data["shmsize"]
            )
            container.start()
            client.close()
            return {"code": self.success_code, "msg": "创建成功: %s" % container.id,"data": []} 
        except Exception as e:
            return  {"code": self.fail_code, "msg": "创建失败: %s" % str(e),"data": []}  

    # 构建镜像
    def build(self, dockerfile, tag):
        try:
            client = self.Client()
            f = BytesIO(dockerfile.encode('utf-8'))
            response = [line for line in client.api.build(fileobj=f, rm=True, tag=tag, nocache=True)]
            res_data = eval(response[-1])
            client.close()
            if "Successfully tagged" in str(res_data):
                return {"code": self.success_code, "msg": "build成功", "data": [res_data]}
            else:
                return  {"code": self.fail_code, "msg": "build失败" ,"data": [res_data]}  
            
        except Exception as e:
            return  {"code": self.fail_code, "msg": "build失败: %s" % str(e),"data": []}  
    
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值