Python Docker SDK docker exec_run在运行时失败

时间:2018-05-24 15:20:51

标签: python docker sdk

Python 2.7.10,Docker Version 18.03.1-ce-mac65(24312)

这可能是我对于docker exec_run命令如何工作缺乏了解,但我正在努力让它工作。以下代码无问题

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()

并返回根目录中的目录列表。然而,我所希望的以下内容将失败。

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()

出现以下错误

/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")

任何人都可以提供任何有关我可能做错的见解吗?

编辑:虽然伊格纳西奥回答了这个问题,但我添加了另一个更接近我想做的答案(针对打开的容器运行多个命令并流式传输输出)。

2 个答案:

答案 0 :(得分:1)

感谢Ignacio。我接着回答了他的反应并且接近了我追求的目标。我认为以下提供了一个更完整的解决方案,用于处理打开的容器,运行多个命令和流输出。容器保持打开状态直至其关闭。您需要在bash会话中打开stdin,否则它不会认为它有任何事情要做并过早关闭。

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()

答案 1 :(得分:0)

我认为问题出在exec_run方法的参数detach = True。

如果设置为true,则执行命令但docker客户端不会附加到输出。

我在测试时发现另一个问题,使用命令/ bin / bash运行容器导致容器在到达exec_run之前结束。

这个脚本对我有用:

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()