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

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

我在Docker容器(它在ENTRYPOINT设置为ENTRYPOINT命令,所以在容器运行后立即执行)运行一个python脚本foo.py,并且无法捕获该脚本的输出。 当我通过正常的CLI使用运行容器

 docker run -v /host_dirpath:/cont_dirpath my_image 

host_dirpath是包含foo.py的目录)我得到打印到stdout的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日志:” – 没有任何东西被捕获在日志中,无论是标准输出或标准错误(我试图引发foo.py中的exception来testing)。

我后面的结果是由foo.py计算的,目前只是用python print语句打印到stdout。 我怎么能得到这个被包含在docker的容器日志,所以我可以从Python内读取? 或者从容器外部以其他方式捕获这个输出?

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

编辑:

docker-py仍然没有运气,但是使用subprocess.Popen以正常的CLI运行容器时,它运行良好 – 在执行此操作时,输出实际上是由stdout正确捕获的。

你正在经历这种行为,因为默认情况下,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参数运行的容器。

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

 docker.wait(contid) 

你的输出看起来是空的,因为还没有记录。