bash 容器的 Docker 超时?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28933925/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Docker timeout for container?
提问by Joel Murphy
For my dissertation at University, I'm working on a coding leaderboard system where users can compile / run untrusted code through temporary docker containers. The system seems to be working well so far, but one problem I'm facing is that when code for an infinite loop is submitted, E.g:
对于我在大学的论文,我正在开发一个编码排行榜系统,用户可以通过临时 docker 容器编译/运行不受信任的代码。到目前为止,系统似乎运行良好,但我面临的一个问题是,当提交无限循环代码时,例如:
while True:
print "infinite loop"
the system goes haywire. The problem is that when I'm creating a new docker container, the Python interpreter prevents docker from killing the child container as data is still being printed to STDOUT (forever). This leads to the huge vulnerability of docker eating up all available system resources until the machine using the system completely freezes (shown below):
系统失控了。问题是,当我创建一个新的 docker 容器时,Python 解释器会阻止 docker 杀死子容器,因为数据仍在打印到 STDOUT(永远)。这导致了 docker 吃掉所有可用系统资源的巨大漏洞,直到使用该系统的机器完全死机(如下所示):
So my question is, is there a better way of setting a timeout on a docker container than my current method that will actually kill the docker container and make my system secure(code originally taken from here)?
所以我的问题是,有没有比我目前的方法更好的方法来设置 docker 容器的超时,它实际上会杀死 docker 容器并使我的系统安全(最初取自此处的代码)?
#!/bin/bash
set -e
to=
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
Edit: The default timeout in my application (passed to the $to
variable) is "10s" / 10 seconds.
编辑:我的应用程序中的默认超时(传递给$to
变量)是“10s”/10 秒。
I've tried looking into adding a timer and sys.exit()
to the python source directly, but this isn't really a viable option as it seems rather insecure because the user could submit code to prevent it from executing, meaning the problem would still persist. Oh the joys of being stuck on a dissertation... :(
我已经尝试研究sys.exit()
直接添加一个计时器和python 源,但这并不是一个真正可行的选项,因为它看起来相当不安全,因为用户可以提交代码来阻止它执行,这意味着问题仍然存在。哦,被困在论文上的乐趣...... :(
回答by Nathaniel Waisbrot
You could set up your container with a ulimit
on the max CPU time, which will kill the looping process. A malicious user can get around this, though, if they're root inside the container.
您可以ulimit
在最大 CPU 时间上设置容器,这将终止循环过程。但是,如果恶意用户是容器内的 root,他们可以绕过这个问题。
There's another S.O. question, "Setting absolute limits on CPU for Docker containers" that describes how to limit the CPU consumption of containers. This would allow you to reduce the effect of malicious users.
还有另一个 SO 问题,“为 Docker 容器设置 CPU 的绝对限制”,描述了如何限制容器的 CPU 消耗。这将允许您减少恶意用户的影响。
I agree with Abdullah, though, that you ought to be able to docker kill
the runaway from your supervisor.
不过,我同意阿卜杜拉的观点,即您应该能够docker kill
摆脱上司的束缚。
回答by Pablo Werlang
I have achieved a solution for this problem.
我已经为这个问题找到了解决方案。
First you must kill docker container when time limit is achieved:
首先,您必须在达到时间限制时终止 docker 容器:
#!/bin/bash
set -e
did=$(docker run -it -d -v "/my_real_path/":/usercode virtual_machine ./usercode/compilerun.sh 2>> /error.txt)
sleep 10 && docker kill $did &> /dev/null && echo -n "timeout" >> /error.txt &
docker wait "$did" &> /dev/null
docker rm -f $ &> /dev/null
The container runs in detached mode (-d option), so it runs in the background. Then you run sleep also in the background. Then wait for the container to stop. If it doesnt stop in 10 seconds (sleep timer), the container will be killed.
容器以分离模式(-d 选项)运行,因此它在后台运行。然后你也在后台运行 sleep 。然后等待容器停止。如果在 10 秒内没有停止(睡眠定时器),容器将被杀死。
As you can see, the docker run process calls a script named compilerun.sh:
如您所见,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
It starts by compiling and running a C program (its my use case, I am sure the same can be done for python compiller).
它首先编译和运行一个 C 程序(这是我的用例,我相信 python 编译器也可以这样做)。
This part:
这部分:
command | head -c 1M > /usercode/output.txt
Is responsible for the max output size thing. It allows output to be 1MB maximum.
负责最大输出大小的事情。它允许输出最大为 1MB。
After that, I just check if file is 1MB. If true, write a message inside (at the beginning of) the output file.
之后,我只检查文件是否为 1MB。如果为 true,则在输出文件内(开头)写入一条消息。
回答by Nitin Tripathi
I guess, you can use signals in python like unix to set timeout. you can use alarm of specific time say 50 seconds and catch it. Following link might help you. signals in python
我想,你可以像 unix 一样在 python 中使用信号来设置超时。您可以使用特定时间的警报,例如 50 秒并捕获它。以下链接可能对您有所帮助。 python中的信号
回答by ctolsen
If you want to run the containers without providing any protection inside them, you can use runtime constraints on resources.
如果您想运行容器而不在其中提供任何保护,您可以对资源使用运行时约束。
In your case, -m 100M --cpu-quota 50000
might be reasonable.
在你的情况下,-m 100M --cpu-quota 50000
可能是合理的。
That way it won't eat up the parent's system resources until you get around to killing it.
这样它就不会吃掉父母的系统资源,直到你想办法杀死它。