Executing interactive commands in docker in python subprocess

When I use docker run interactively, I can run commands that I want to test for some python stuff.

root@pydock:~# docker run -i -t dockerfile/python /bin/bash
[ root@197306c1b256:/data ]$ python -c "print 'hi there'"
hi there
[ root@197306c1b256:/data ]$ exit
exit
root@pydock:~#

      

I want to automate this from python using the subprocess module, so I wrote this:

run_this = "print('hi')"
random_name = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(20))
command = 'docker run -i -t --name="%s" dockerfile/python /bin/bash' % random_name
subprocess.call([command],shell=True,stderr=subprocess.STDOUT)
command = 'cat <<\'PYSTUFF\' | timeout 0.5 python | head -n 500000 \n%s\nPYSTUFF' % run_this
output = subprocess.check_output([command],shell=True,stderr=subprocess.STDOUT)
command = 'exit'
subprocess.call([command],shell=True,stderr=subprocess.STDOUT)
command = 'docker ps -a | grep "%s" | awk "{print $1}" | xargs --no-run-if-empty docker rm -f' % random_name
subprocess.call([command],shell=True,stderr=subprocess.STDOUT)

      

It is supposed to create a container, run python command on the container and exit and delete the container. It does all of this, except that the command is run on the host machine and not in a docker container. I guess the docker is switching projectiles or something. How do I start a python subprocess from a new shell?

+3


source to share


2 answers


You really need to create a new child in the new shell that you open. So, then docker creation

run docker enter

or try the same operation with pexpect

instead of a subprocess. `pexpect spawns a new child and that way you can send commands.



+1


source


It sounds like you are expecting the second command cat <<...

to send input to the first command. But the two subprocess commands have nothing to do with each other, so this doesn't work.

The Python subprocess

library
and the command popen

behind it offer a way to get a pipe for stdin to process. This way you can send the commands you want directly from Python and not try to force another subprocess to talk to it.

So something like:



from subprocess import Popen, PIPE

p = Popen("docker run -i -t --name="%s" dockerfile/python /bin/bash", stdin=PIPE)
p.communicate("timeout 0.5 python | head -n 500000 \n" % run_this) 

      

(I'm not a Python expert, apologies for the errors in string formation. Adapted from this answer )

+1


source







All Articles