Donentolon
Donentolon

Reputation: 1581

How do I use Python to launch an interactive Docker container?

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

Answers (2)

Philippe
Philippe

Reputation: 26592

Can we use this ?

import os
os.system('docker run -it --rm ubuntu bash')

Upvotes: 2

prithajnath
prithajnath

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

Related Questions