捕获python脚本的输出在docker容器内运行

acr*_*acr 23 python linux docker dockerpy

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

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

docker run -v /host_dirpath:/cont_dirpath my_image
Run Code Online (Sandbox Code Playgroud)

(host_dirpath是包含foo.py的目录)我得到foo.py的预期输出打印到stdout,这只是一个键值对的字典.但是,我正在尝试使用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))
Run Code Online (Sandbox Code Playgroud)

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

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

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

编辑:

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

Tho*_*eil 20

您遇到此行为,因为python默认缓冲其输出.

举个例子:

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

while True:
    print "f00"
    sleep(1)
Run Code Online (Sandbox Code Playgroud)

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

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

但如果使用-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
Run Code Online (Sandbox Code Playgroud)

您还可以注入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
Run Code Online (Sandbox Code Playgroud)

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

  • 使用`-u`运行Python并没有改变任何东西.只有'PYTHONUNBUFFERED = 0'才适合我. (2认同)
  • 设置 PYTHONUNBUFFERED=1 或 PYTHONUNBUFFERED=TRUE 的清理器。(0 也有效,因为在这种情况下任何值都被视为真。但是,它更令人困惑,因为 0 通常意味着假)。 (2认同)