我正在尝试对我的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 ))"
因此基本上“ $ ...”没有得到评估,我也不知道该如何解决。
答案 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
(和ENTRYPOINT
和RUN
)命令有两种形式。您写的表格是首选:
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传递。