捕获在docker中运行的python脚本的输出包含

2024-04-20 12:35:22 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

docker run -v /host_dirpath:/cont_dirpath my_image

host_dirpath是包含foo.py的目录)我将foo.py的预期输出打印到stdout,stdout只是一个键值对字典。但是,我试图在python中使用docker py模块来实现这一点,并且不知怎么的,脚本输出并没有被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 logs:”—日志中没有捕获任何内容,无论是stdout还是stderr(我试图在foo.py中引发一个异常来测试这一点)。

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

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

编辑:

DockerPy仍然不太好用,但是它在使用subprocess.Popen使用普通的CLI运行容器时运行得很好-这样做时stdout确实正确地获取了输出。


Tags: 模块dockerrunpyimage脚本hostfoo
2条回答

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

docker.wait(contid)

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

您正经历这种行为,因为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参数运行的容器。

相关问题 更多 >