问题
Python 2.7.10, Docker Version 18.03.1-ce-mac65 (24312)
This may be a lack of understanding on my part as to how the docker exec_run command works but I'm struggling to get it to work. The following code works without issue
from __future__ import print_function
import docker
if __name__ == '__main__':
client = docker.from_env()
image = client.images.pull('oraclelinux:7')
container = client.containers.run('oraclelinux:7',
command='ls',
stderr=True,
stdout=True,
auto_remove=False,
remove=False,
detach=True
)
log = container.logs(stdout=True, stderr=True, stream=True)
for line in log:
print(line, end='')
container.stop()
print(container.status)
container.remove()
And returns a list of directories in the root directory. However the following which I had hoped would be equivalent fails.
from __future__ import print_function
import docker
if __name__ == '__main__':
client = docker.from_env()
image = client.images.pull('oraclelinux:7')
container = client.containers.create('oraclelinux:7',
command='/bin/bash',
auto_remove=False)
container.start()
log = container.exec_run('ls',
stderr=True,
stdout=True,
detach=True)
for line in log:
print(line, end='')
container.stop()
print(container.status)
container.remove()
with the following error
/Users/user/PythonVirtualEnv/bin/python "/Users/user/DockerAutomation.py"
Traceback (most recent call last):
File "/Users/user/DockerAutomation.py", line 16, in <module>
detach=True)
File "/Users/user/PythonVirtualEnv/lib/python2.7/site-packages/docker/models/containers.py", line 185, in exec_run
resp['Id'], detach=detach, tty=tty, stream=stream, socket=socket
File "/Users/user/PythonVirtualEnv/lib/python2.7/site-packages/docker/utils/decorators.py", line 19, in wrapped
return f(self, resource_id, *args, **kwargs)
File "/Users/user/PythonVirtualEnv/lib/python2.7/site-packages/docker/api/exec_api.py", line 162, in exec_start
return self._result(res)
File "/Users/user/PythonVirtualEnv/lib/python2.7/site-packages/docker/api/client.py", line 231, in _result
self._raise_for_status(response)
File "/Users/user/PythonVirtualEnv/lib/python2.7/site-packages/docker/api/client.py", line 227, in _raise_for_status
raise create_api_error_from_http_exception(e)
File "/Users/user/PythonVirtualEnv/lib/python2.7/site-packages/docker/errors.py", line 31, in create_api_error_from_http_exception
raise cls(e, response=response, explanation=explanation)
docker.errors.APIError: 500 Server Error: Internal Server Error ("OCI runtime exec failed: exec failed: container_linux.go:348: starting container process caused "process_linux.go:86: executing setns process caused \"exit status 21\"": unknown")
Can anyone offer any insight into what I might be doing wrong?
Edit : Whilst Ignacio answered the question, I've added another answer which comes closer to what I wanted to do (run multiple commands against an open container and stream the output).
回答1:
I think the problem is at the parameter detach=True of the exec_run method.
With it set to true, command is executed but the docker client doesn't attach to the outputs.
I found another issue while testing, running the container with the command /bin/bash cause the container to end before even reaching exec_run.
This script have worked for me:
from __future__ import print_function
import docker
if __name__ == '__main__':
client = docker.from_env()
image = client.images.pull('oraclelinux:7')
container = client.containers.create('oraclelinux:7',
command='sleep 10000',
auto_remove=False)
container.start()
log = container.exec_run('ls',
stderr=True,
stdout=True)
for line in log:
print(line, end='')
container.stop()
print(container.status)
container.remove()
回答2:
Thanks to Ignacio. I followed through on his response and got closer to what I was after. I think the following provides a more complete solution for working with the opened container, running multiple commands and streaming the output. The container stays open until it's closed. You need to open stdin on the bash session otherwise it's doesn't think it has anything to do and closes prematurely.
from __future__ import print_function
from time import time
import docker
if __name__ == '__main__':
client = docker.from_env()
image = client.images.pull('oraclelinux:7')
start = time()
container = client.containers.create('oraclelinux:7',
command="/bin/bash",
tty=True,
stdin_open=True,
auto_remove=False)
container.start()
print('Container Started : {}'.format(container.status))
exec_log = container.exec_run("/bin/bash -c 'for i in `seq 1 10`; do echo $i; sleep 1;done;'",
stdout=True,
stderr=True,
stream=True)
for line in exec_log[1]:
print(line, end='')
print('Container Finished outputting log : {}'.format(time() - start))
container.stop()
container.remove()
来源:https://stackoverflow.com/questions/50512912/python-docker-sdk-docker-exec-run-fails-whilst-run-works