如何在dockerfile中传递运行时参数?

时间:2018-07-27 15:31:25

标签: docker dockerfile gunicorn

我正在尝试对我的django项目进行docker化,以便使用我使用的shell中的gunicorn运行该项目:

gunicorn --bind :8000 --workers $(( 2 * `cat /proc/cpuinfo | grep 'core id' | wc -l` + 1 )) MyQ.wsgi:application

效果很好, 这个想法是利用gunicorn文档中定义的尽可能多的内核。

$(((2 * cat /proc/cpuinfo | grep 'core id' | wc -l + 1))部分仅返回2 * n + 1,其中n是系统中的核心数量。

但是,我在将此命令重写为Dockerfile时遇到了一些麻烦,这是我目前的尝试:

CMD ["gunicorn", "--bind :8000", "--workers", "$(( 2 * `cat /proc/cpuinfo | grep 'core id' | wc -l` + 1 ))", "MyQ.wsgi:application"]

当我运行docker run时,崩溃并显示以下错误:

gunicorn: error: argument -w/--workers: invalid int value: "$(( 2 * `cat /proc/cpuinfo | grep 'core id' | wc -l` + 1 ))"

因此基本上“ $ ...”没有得到评估,我也不知道该如何解决。

3 个答案:

答案 0 :(得分:2)

我认为最好在ENV中用Dockerfile指令定义一个环境变量,并在CMD指令中使用它。这样,您就可以从Container创建Docker Image时设置环境变量。

在您的Dockerfile中定义这样的环境变量:

ENV WORKERS 1

然后将您的CMD指令更改为此:

CMD ["sh", "-c", "gunicorn --bind :8000 --workers $WORKERS MyQ.wsgi:application"]

最后,在创建Container时,将WORKERS环境变量与-e参数一起传递。

答案 1 :(得分:1)

CMD(和ENTRYPOINTRUN)命令有两种形式。您写的表格是首选:

CMD ["command_name", "--option", "value"]

但是,它不会运行shell来预处理命令行。因此,例如,如果您运行

CMD ["ls", ">", "/host/directory/foo.ls"]

它将>作为参数传递给程序,而不进行shell重定向。

因此,要使您的构造正常工作,您需要使用另一种形式,该形式会将其隐式包装在外壳执行程序中(/bin/sh -c '...'

CMD gunicorn --bind :8000 ...

实际上,您并不是想要通过Dockerfile来强制运行时约束(如工作人员计数)的方法;您应该允许在docker run命令或类似命令中指定类似的内容。 @HassanMusavi的答案是更好的答案。

答案 2 :(得分:0)

Dockerfile不支持运行时参数(要在运行docker文件时计算)。但是根据您的情况,您可以编写脚本“ test.sh”,其中包含带有参数的gunicorn条目。

然后在CMD中定义脚本路径,例如CMD["test.sh"]。因此,当您从该映像创建容器时,它将在容器中运行脚本并评估$ expression并在运行时获取核心(即使cat /proc/cpuinfo将在您的容器中运行,但它将列出核心您的docker机器)。这样,您不必依赖计算核并将其作为-e传递。