Docker-py: docker stats equivalent

Created on 5 Apr 2017  Â·  9Comments  Â·  Source: docker/docker-py

I took a look to the documentation but by doing:

cli=docker.from_env()

server=cli.containers.run(...)

server.stats()

Output:

I didnt get the expected results. I was only able to get the stats with the low level API:

client=..

sts=client.stats(container=..)

and even under that command I didnt get the CPU and Memory percentages that sudo docker stats provides.

(sudo docker stats)

ID CPU CPU% Memory Memory% ..

Could you please provide the call to obtain the CPU and memory percentages, as it is not clear to me in the documentation.

Also I tried the following equation and I didnt obtained the same percentage as docker stats:

    cpuDelta = (sts.CPUStats.CPUUsage.TotalUsage) - (previousCPU.CPUUsage.TotalUsage)

    systemDelta = (v.CPUStats.SystemUsage) - (previousSystem.CPUStats.SystemUsage)


    cpuPercent = float(cpuDelta / systemDelta) * float(len(sts.CPUStats.CPUUsage.PercpuUsage)) * 100.0
kinquestion

Most helpful comment

Is it possible to get stats() from multiple containers like in docker stats without delay? E.g.:

>>> client.containers.list()
[<Container: f601c3673a>, <Container: 64c05a8adc>, <Container: 553056c89b>, <Container: 865c8b3e99>]
>>> for container in client.containers.list():
...     stats = container.stats(stream=False)
...     print(stats)

will print stats() with delay for each container. It would be nice to have something like:

client.containers.stats([<Container: f601c3673a>, <Container: 64c05a8adc>], stream=False)

Is there anything similar?

All 9 comments

The output should match what is returned by the API. https://docs.docker.com/engine/api/v1.27/#operation/ContainerStats

It's very likely that percentages are computed by the CLI on the client-side.

Is it possible to get stats() from multiple containers like in docker stats without delay? E.g.:

>>> client.containers.list()
[<Container: f601c3673a>, <Container: 64c05a8adc>, <Container: 553056c89b>, <Container: 865c8b3e99>]
>>> for container in client.containers.list():
...     stats = container.stats(stream=False)
...     print(stats)

will print stats() with delay for each container. It would be nice to have something like:

client.containers.stats([<Container: f601c3673a>, <Container: 64c05a8adc>], stream=False)

Is there anything similar?

@sheirys Unfortunately, the API only supports a single container at a time. The way the docker stats does it is by starting connection per container and combining the results.

I just wanted to ask, so can this be done using python like by using multi threading or a different module? Or is this not possible at all?

It's possible, and yes you'll probably need threading.
You can refer to the CLI code to figure out how it's done there ( https://github.com/docker/cli/blob/master/cli/command/container/stats.go ) - it's in Go, but uses the same API.

You can do this in python with the following code, just simply combine it with the multiprocessing python library and call each stats on a different process.

import docker

client=docker.from_env()

client_lowlevel = docker.APIClient(base_url='unix://var/run/docker.sock')

client1_stats=client_lowlevel.stats(container="server1",decode=True, stream=False)
client2_stats=client_lowlevel.stats(container="server2",decode=True, stream=False)

Get Outlook for Androidhttps://aka.ms/ghei36


From: Joffrey F notifications@github.com
Sent: Friday, January 26, 2018 7:16:36 PM
To: docker/docker-py
Cc: Chuseuiti; Author
Subject: Re: [docker/docker-py] docker stats equivalent (#1546)

It's possible, and yes you'll probably need threading.
You can refer to the CLI code to figure out how it's done there ( https://github.com/docker/cli/blob/master/cli/command/container/stats.go ) - it's in Go, but uses the same API.

—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHubhttps://github.com/docker/docker-py/issues/1546#issuecomment-360940585, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AF8yeBRBelIEQz5KgWTtfMowSwSRvkq7ks5tOmrkgaJpZM4Mzr67.

This is a full example, I didnt test it but it should do what you were mentioning. Parallel retrieval of the stats

import docker
import multiprocessing as mp

output = mp.Queue()

def stats(server):
    client=docker.from_env()
    client_lowlevel = docker.APIClient(base_url='unix://var/run/docker.sock')
    client_stats=client_lowlevel.stats(container=server,decode=True, stream=False)
    output.put(client_stats)

processes =[ mp.Process(target=stats, args=(server)) for server in ['server1','server2']]

# Run processes
for p in processes:
    p.start()

# Exit the completed processes
for p in processes:
    p.join()


Edit. You could always put that code in a function to obtain the execution that you were mentioning

client.containers.stats([<Container: f601c3673a>, <Container: 64c05a8adc>], stream=False)

Thank you guys @Chuseuiti @shin- ! I will let you know how it goes and possible post my final code here. Thank you again!

hi @shabbirkagalwala, @Chuseuiti @shin & all if you guys have got success in the above scenario, could please add your code over here for reference to all of us in need

Here's what I have tried so far, but getting some error, check stackstrace error

import docker
DOCKER_CLIENT = docker.DockerClient(base_url='unix://var/run/docker.sock')
#RUNNING = 'running'

#def is_running(container_name):
def is_running():
    """
    verify the status of a sniffer container by it's name
    :param container_name: the name of the container
    :return: Boolean if the status is ok
    """
#    container = DOCKER_CLIENT.containers.get(container_name)

#    container_state = container.attrs['State']

#    container_is_running = container_state['Status'] == RUNNING

    runContainers = DOCKER_CLIENT.containers.list()

    #return container_is_running
    return runContainers

#my_container_name = "pdb"
runningContainers=is_running()
#print(is_running(my_container_name))
print(runningContainers)

for i in runningContainers:
    print(i)
    client=docker.from_env()
    client_lowlevel = docker.APIClient(base_url='unix://var/run/docker.sock')
    client_stats=client_lowlevel.stats(container=i,decode=False, stream=False)
    print(client_stats)
    print(" ")


[<Container: 5c4fc26776>, <Container: a2ed96ac60>, <Container: 95cd154736>, <Container: 60be6aeb9d>, <Container: 5d869677d3>]
<Container: 5c4fc26776>
Traceback (most recent call last):
  File "py-running.py", line 32, in <module>
    client_stats=client_lowlevel.stats(container=i,decode=False, stream=False)
  File "/home/drsab/.local/lib/python3.6/site-packages/docker/utils/decorators.py", line 19, in wrapped
    return f(self, resource_id, *args, **kwargs)
  File "/home/drsab/.local/lib/python3.6/site-packages/docker/api/container.py", line 1132, in stats
    url = self._url("/containers/{0}/stats", container)
  File "/home/drsab/.local/lib/python3.6/site-packages/docker/api/client.py", line 252, in _url
    'instead'.format(arg, type(arg))
ValueError: Expected a string but found <Container: 5c4fc26776> (<class 'docker.models.containers.Container'>) instead


Was this page helpful?
0 / 5 - 0 ratings