容器的Docker超时?

时间:2015-03-09 01:24:44

标签: python bash shell unix docker

对于我在大学的论文,我正在开发一个编码排行榜系统,用户可以通过临时的docker容器编译/运行不受信任的代码。到目前为止,该系统似乎运行良好,但我面临的一个问题是,当提交无限循环的代码时,例如:

while True:
   print "infinite loop"
系统变得混乱。问题是当我创建一个新的docker容器时,Python解释器阻止docker杀死子容器,因为数据仍然被打印到STDOUT(永远)。这导致docker占用所有可用系统资源的巨大漏洞,直到使用该系统的机器完全冻结(如下所示):

enter image description here

所以我的问题是,是否有更好的方法在docker容器上设置超时,而不是我当前的方法杀死docker容器并使我的系统安全(代码最初取自{ {3}})?

#!/bin/bash
set -e

to=$1
shift

cont=$(docker run --rm "$@")
code=$(timeout "$to" docker wait "$cont" || true)
docker kill $cont &> /dev/null
echo -n 'status: '
if [ -z "$code" ]; then
    echo timeout
else
    echo exited: $code
fi

echo output:
# pipe to sed simply for pretty nice indentation
docker logs $cont | sed 's/^/\t/'

docker rm $cont &> /dev/null

编辑:我的应用程序中的默认超时(传递给$to变量)是“10s”/ 10秒。


我已经尝试过直接向python源添加一个计时器和sys.exit(),但这不是一个可行的选项,因为它似乎相当不安全,因为用户可以提交代码以防止它执行,意思是问题仍然存在。哦,被困在论文上的乐趣...... :(

5 个答案:

答案 0 :(得分:3)

您可以在最大CPU时间内使用ulimit设置容器,这将终止循环过程。但是,恶意用户可以解决这个问题,如果他们在容器内部扎根。

还有另一个S.O.问题," Setting absolute limits on CPU for Docker containers"描述了如何限制容器的CPU消耗。这样可以减少恶意用户的影响。

我同意阿卜杜拉的观点,你应该能够docker kill你的主管失控。

答案 1 :(得分:1)

我已经解决了这个问题。

首先,你必须在达到时间限制时杀死docker容器:

#!/bin/bash
set -e
did=$(docker run -it -d -v "/my_real_path/$1":/usercode virtual_machine ./usercode/compilerun.sh 2>> $1/error.txt)
sleep 10 && docker kill $did &> /dev/null && echo -n "timeout" >> $1/error.txt &
docker wait "$did" &> /dev/null
docker rm -f $ &> /dev/null

容器以分离模式(-d选项)运行,因此它在后台运行。 然后你也在后台运行睡眠。 然后等待容器停止。如果它在10秒内没有停止(睡眠定时器),容器将被杀死。

如您所见,docker run进程调用名为compilerun.sh的脚本:

#!/bin/bash
gcc -o /usercode/file /usercode/file.c 2> /usercode/error.txt && ./usercode/file < /usercode/input.txt | head -c 1M > /usercode/output.txt
maxsize=1048576
actualsize=$(wc -c <"/usercode/output.txt")
if [ $actualsize -ge $maxsize ]; then
    echo -e "1MB file size limit exceeded\n\n$(cat /usercode/output.txt)" > /usercode/output.txt
fi

首先编译并运行一个C程序(我的用例,我相信python compiller也可以这样做。)

这部分:

command | head -c 1M > /usercode/output.txt

负责最大输出尺寸的事情。它允许输出最大为1MB。

之后,我只检查文件是否为1MB。如果为true,则在输出文件的内部(开头)写一条消息。

答案 2 :(得分:1)

如果超过超时时间,--stop-timeout 选项不会终止容器。

相反,如果超时,则使用 --ulimit --cpu=timeout 终止容器。 这是基于容器内进程的 CPU 时间。

答案 3 :(得分:0)

我想,你可以使用像unix这样的python中的信号来设置超时。你可以使用50秒的特定时间的警报并抓住它。以下链接可能对您有帮助。 signals in python

答案 4 :(得分:0)

在运行 docker 容器时使用 --stop-timeout 选项。一旦超时发生,这将执行 SIGKILL