如何在 docker 上运行 gunicorn

Posted

技术标签:

【中文标题】如何在 docker 上运行 gunicorn【英文标题】:how to run gunicorn on docker 【发布时间】:2017-10-11 01:13:12 【问题描述】:

docker 启动时,我有 2 个相互依赖的文件。 1 是一个烧瓶文件,一个是具有几个功能的文件。当 docker 启动时,只会执行函数文件,但它会从烧瓶文件中导入烧瓶变量。示例:

Flaskfile

import flask
from flask import Flask, request
import json

_flask = Flask(__name__)

@_flask.route('/', methods = ['POST'])
def flask_main():
    s = str(request.form['abc'])
    ind = global_fn_main(param1,param2,param3)
    return ind

def run(fn_main):
    global global_fn_main
    global_fn_main = fn_main
    _flask.run(debug = False, port = 8080, host = '0.0.0.0', threaded = True)

主文件

import flaskfile
#a few functions then
if__name__ == '__main__':
    flaskfile.run(main_fn)

脚本运行良好,无需 gunicorn。

Dockerfile

  FROM python-flask
  ADD *.py *.pyc /code/
  ADD requirements.txt /code/
  WORKDIR /code
  EXPOSE 8080
  CMD ["python","main_file.py"]

在命令行中:我通常这样做:docker run -it -p 8080:8080 my_image_name 然后 docker 将启动并监听。

现在使用 gunicorn: 我试图将 dockerfile 中的CMD 参数修改为

["gunicorn", "-w", "20", "-b", "127.0.0.1:8083", "main_file:flaskfile"]

但它只是不断退出。我写的 docker gunicorn 命令不对吗?

【问题讨论】:

容器退出时你看到了什么错误? 【参考方案1】:

我这周刚刚解决了这个问题,一路上偶然发现了你的问题。公平地说,您现在要么解决了这个问题,要么改变了方法,但为了未来:

我的 Dockerfile 中的命令是:

CMD ["gunicorn"  , "-b", "0.0.0.0:8000", "app:app"]

第一个“app”是模块,第二个“app”是 WSGI 可调用的名称,在您的情况下,它应该是代码中的 _flask,尽管您还有其他一些发生的事情让我不太确定。

Gunicorn 取代了代码中的所有运行语句,如果 Flask 的开发 Web 服务器和 Gunicorn 尝试使用相同的端口,它可能会发生冲突并导致 Gunicorn 崩溃。

请注意,当由 Gunicorn 运行时,__name__ 不是“主”。在我的示例中,它等于“app”。

在我公认的 Python、Docker 和 Gunicorn 初级水平的情况下,最快的调试方法是注释掉 Dockerfile 中的“CMD”,让容器启动并运行:

docker run -it -d -p 8080:8080 my_image_name

跳到正在运行的容器上:

 docker exec -it container_name /bin/bash

然后从命令行启动 Gunicorn,直到你让它工作,然后用 curl 测试 - 我在我的 app.py 文件中保留了一个基本路由,它只打印出“Hi”并且没有验证服务器的依赖项是在担心端口绑定到主机之前。

【讨论】:

端口 8080 还是 8000? 第二个例子只是为了快速调试,不会冲突- 8000是设置正常运行 在 CMD 8080 或 -p anyport:8000 中 谢谢,这解决了我无法连接的问题。 Gunicorn 默认绑定到 127.0.0.1,外部无法访问(例如通过 Docker 的端口转发)。 @Fax 你的评论为我澄清了一些事情。谢谢!【参考方案2】:

在过去 3 天努力解决这个问题后,我发现您需要做的就是绑定到不可路由的元地址 0.0.0.0 而不是环回 IP 127.0.0.1

CMD ["gunicorn" , "--bind", "0.0.0.0:8000", "app:app"]

不要忘记公开端口,一种选择是使用 EXPOSE 在你的 Dockerfile 中:

EXPOSE 8000

现在:

docker build -t test .

终于可以运行了:

docker run -d -p 8000:8000 test

【讨论】:

0.0.0.0 表示:绑定所有可用的接口,包括localhost,也称为“127.0.0.1” 感谢@kalou.net。请检查它现在是否已修复【参考方案3】:

这是我使用 Django App 编写的 Dockerfile 的最后一部分

EXPOSE 8002
COPY entrypoint.sh /code/
WORKDIR /code
ENTRYPOINT ["sh", "entrypoint.sh"]

然后在 entrypoint.sh 中

#!/bin/bash

# Prepare log files and start outputting logs to stdout
mkdir -p /code/logs
touch /code/logs/gunicorn.log
touch /code/logs/gunicorn-access.log
tail -n 0 -f /code/logs/gunicorn*.log &

export DJANGO_SETTINGS_MODULE=django_docker_azure.settings

exec gunicorn django_docker_azure.wsgi:application \
    --name django_docker_azure \
    --bind 0.0.0.0:8002 \
    --workers 5 \
    --log-level=info \
    --log-file=/code/logs/gunicorn.log \
    --access-logfile=/code/logs/gunicorn-access.log \
"$@"

希望对你有用

【讨论】:

这部分会是什么样子? exec gunicorn django_docker_azure.wsgi:application 我可以用exec gunicorn my_docker_image.wsgi:application 吗? 那部分与 django 应用程序有关,我曾经使用过烧瓶,所以我无法给你提示。对不起【参考方案4】:

这对我有用:

FROM docker.io/python:3.7

WORKDIR /app

COPY requirements.txt ./

RUN pip install --no-cache-dir -r requirements.txt

ENV GUNICORN_CMD_ARGS="--bind=0.0.0.0 --chdir=./src/"
COPY . .

EXPOSE 8000

CMD [ "gunicorn", "app:app" ]

【讨论】:

【参考方案5】:

gunicorn main:app --workers 4 --bind :3000 --access-logfile '-'

【讨论】:

请在您的答案中添加更多详细信息,尝试解释提出问题的人做错了什么以及您的解决方案为何有效。谢谢【参考方案6】:

我也在尝试运行烧瓶应用程序。我发现你可以使用

ENTRYPOINT['gunicorn', '-b', ':8080', 'app:APP']

这将获取您指定的文件并在 docker 实例上运行。另外,如果您正在运行 Debug LOG-LEVEL,请不要忘记顶部的 shebang #!/usr/bin/env python

【讨论】:

以上是关于如何在 docker 上运行 gunicorn的主要内容,如果未能解决你的问题,请参考以下文章

如何在 gunicorn(django) + nginx + docker 中更改缓冲区大小

django 和 gunicorn 在 docker 容器内运行时,无法在 ec2 上使用 nginx 提供静态文件

如何运行多个Django App Gunicorn systemd?

gunicorn Flask 应用程序在 Docker 中挂起

如何在 Amazon EC2 上使用 Gunicorn 设置 Nginx 代理缓冲?

如何运行与 gunicorn 绑定的 django 应用程序?