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

时间:2014-05-07 18:01:44

标签: python linux docker dockerpy

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

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

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

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

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

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

非常感谢任何帮助。提前谢谢!

编辑:

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

2 个答案:

答案 0 :(得分:20)

您遇到此行为,因为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参数的情况下运行的容器。

答案 1 :(得分:3)

由于启动的容器与控制程序并行运行,因此您可能会遇到竞争状况。在抓取日志之前,您需要等待容器启动和完成。在docker.start。

之后立即将docker.wait添加到您的代码中
docker.wait(contid)

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