Reputation: 455
Python noob here, I'm trying to use the exec_run
function from docker-py
to send commands to a detached docker container and have the output hitting stdout in real time. Here's a MWE:
import docker, sys
client = docker.from_env()
# start a detached container
box = client.containers.run(image = "ubuntu",
remove = True,
detach = True,
tty = True,
command = "/bin/bash")
# send a test command
box.exec_run(cmd = "find /") # gives no output in the terminal when run
# same again, but save the output
run = box.exec_run(cmd = "find /")
print(run.output.decode("utf-8"))
box.stop()
sys.exit()
I can grab the output after the fact by storing it in a variable, but I can't seem to get the real time output. I actually want to give it long running processes, so it's preferable to see the output as it happens (as well as saving it). Is this difficult to do, or am I missing something really basic here?
Upvotes: 5
Views: 4834
Reputation: 650
I implemented the desired behavior like that:
def install_model(self, language: str) -> bool:
if self.container:
_, stream = self.container.exec_run(
cmd=f"lima_models.py -l {language}", stream=True)
for data in stream:
print(data.decode(), end='')
print()
As you can see, I use stream=True
and then iterate over the result. I print the decoded data but you could also store it for later use. The executed command produces a progress bar using \r
at the beginning of each output line. This is why add the end=''
parameter.
Here is your MWE modified with the above solution:
import docker, sys
client = docker.from_env()
# start a detached container
box = client.containers.run(image = "ubuntu",
remove = True,
detach = True,
tty = True,
command = "/bin/bash")
# send a test command
_, stream = box.exec_run(cmd = "find /", stream=True)
for data in stream:
print(data.decode())
box.stop()
sys.exit()
Upvotes: 1
Reputation: 265
The command
parameter in the client.containers.run
function is that what you're looking for.
It may take even a list of commands, doc (link):
command (str or list) – The command to run in the container.
So, simply replace command = "/bin/bash"
with bash -c "echo $(find /)"
.
In case if you want to keep the docker container alive and execute commands one by one - create detached container and simply use exec_run
:
container = client.containers.run(image='ubuntu', auto_remove=False, stdin_open=True, detach=True)
container.exec_run(cmd='echo $(find /)')
Upvotes: 0