Reputation: 1581
I am working with a Docker image which I launch in interactive mode like so: docker run -it --rm ubuntu bash
The actual image I work with has many complicated parameters, which is why I wrote a script to construct the full docker run
command and launch it for me. As the logic grew more complicated, I want to migrate the script from bash to Python.
Using docker-py
, I prepared everything to run the image. Seems like using docker.containers.run
for interactive shells is not supported, however. Using subprocess
instead seems logical, so I tried the following:
import subprocess
subprocess.Popen(['docker', 'run', '-it', '--rm', 'ubuntu', 'bash'])
But this gives me:
$ python3 docker_run_test.py
$ unable to setup input stream: unable to set IO streams as raw terminal: input/output error
$
Note that the error message appears in a different shell prompt from the python command.
How do I make python3 docker_run_test.py
to do equivalent of running docker run -it --rm ubuntu bash
?
Upvotes: 6
Views: 5866
Reputation: 26592
Can we use this ?
import os
os.system('docker run -it --rm ubuntu bash')
Upvotes: 2
Reputation: 2115
You can use a pseudo-terminal to read from and write to the container process
import pty
import sys
import select
import os
import subprocess
pty, tty = pty.openpty()
p = subprocess.Popen(['docker', 'run', '-it', '--rm', 'ubuntu', 'bash'], stdin=tty, stdout=tty, stderr=tty)
while p.poll() is None:
# Watch two files, STDIN of your Python process and the pseudo terminal
r, _, _ = select.select([sys.stdin, pty], [], [])
if sys.stdin in r:
input_from_your_terminal = os.read(sys.stdin.fileno(), 10240)
os.write(pty, input_from_your_terminal)
elif pty in r:
output_from_docker = os.read(pty, 10240)
os.write(sys.stdout.fileno(), output_from_docker)
Upvotes: 2