【问题标题】:Capturing output of python script run inside a docker container捕获在 docker 容器内运行的 python 脚本的输出
【发布时间】:2014-06-24 20:29:45
【问题描述】:

这里的目的是使用 docker 容器作为安全沙箱来运行不受信任的 python 脚本,但要在 python 中使用 docker-py 模块执行此操作,并且能够捕获该脚本的输出。

我在 docker 容器中运行 python 脚本 foo.py(它在我的 Dockerfile 中设置为 ENTRYPOINT 命令,所以它在容器运行后立即执行)并且无法捕获它的输出脚本。当我使用

通过普通 CLI 运行容器时
docker run -v /host_dirpath:/cont_dirpath my_image

host_dirpath 是包含 foo.py 的目录)我将 foo.py 的预期输出打印到标准输出,这只是一个键值对字典。但是,我正在尝试使用 docker-py 模块从 python 中执行此操作,并且不知何故,logs 方法没有捕获脚本输出。这是我正在使用的python代码:

from docker import Client

docker = Client(base_url='unix://var/run/docker.sock',
              version='1.10',
              timeout=10)

contid = docker.create_container('my_image', volumes={"/cont_dirpath":""})
docker.start(contid, binds={"/host_dirpath": {"bind": "/cont_dirpath"} })

print "Docker logs: " + str(docker.logs(contid))

这只会导致“Docker 日志:” - 日志中没有捕获任何内容,stdout 和 stderr 都没有(我尝试在 foo.py 中引发异常来测试这一点)。

我所追求的结果是由 foo.py 计算的,目前只是使用 python print 语句打印到标准输出。如何将它包含在 docker 容器日志中,以便我可以从 python 中读取它?或者以其他方式从容器外部捕获此输出?

任何帮助将不胜感激。提前致谢!

编辑:

docker-py 仍然没有运气,但是在使用 subprocess.Popen 使用普通 CLI 运行容器时它运行良好 - 执行此操作时,输出确实被 stdout 正确抓取。

【问题讨论】:

标签: python linux docker dockerpy


【解决方案1】:

您遇到此行为是因为默认情况下 python 会缓冲其输出。

举个例子:

vagrant@docker:/vagrant/tmp$ cat foo.py
#!/usr/bin/python
from time import sleep

while True:
    print "f00"
    sleep(1)

然后从作为守护进程运行的容器中观察日志不会显示任何内容:

vagrant@docker:/vagrant/tmp$ docker logs -f $(docker run -d -v $(pwd):/app dockerfile/python python /app/foo.py)

但是如果你使用-u 命令行参数禁用python缓冲输出,一切都会显示出来:

vagrant@docker:/vagrant/tmp$ docker logs -f $(docker run -d -v $(pwd):/app dockerfile/python python -u /app/foo.py)
f00
f00
f00
f00

你也可以注入PYTHONUNBUFFERED环境变量:

vagrant@docker:/vagrant/tmp$ docker logs -f $(docker run -d -v $(pwd):/app -e PYTHONUNBUFFERED=0 dockerfile/python python /app/foo.py)
f00
f00
f00
f00

请注意,此行为仅影响在没有 -t--tty 参数的情况下运行的容器。

【讨论】:

  • 非常感谢!坚持使用我永远运行的 python 脚本一个小时来寻找输出。
  • 使用-u 运行 Python 并没有改变任何东西。只有PYTHONUNBUFFERED=0 为我工作。
  • 清除器设置 PYTHONUNBUFFERED=1 或 PYTHONUNBUFFERED=TRUE。 (0 也可以,因为在这种情况下任何值都被视为真。但是,它更令人困惑,因为 0 通常意味着假)。
【解决方案2】:

由于启动的容器与您的控制程序并行运行,您可能会遇到竞争情况。在获取日志之前,您需要等待容器启动和完成。在 docker.start 之后立即将 docker.wait 添加到您的代码中。

docker.wait(contid)

您的输出似乎为空,因为尚未记录任何内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 2020-12-31
    • 1970-01-01
    • 2022-11-25
    • 2018-10-06
    • 2019-08-27
    • 1970-01-01
    相关资源
    最近更新 更多