【问题标题】:How to run nginx and gunicorn in same docker container如何在同一个 docker 容器中运行 nginx 和 gunicorn
【发布时间】:2021-10-06 19:24:36
【问题描述】:

我正在尝试使用 gunicorn 和 nginx 部署 python 烧瓶应用程序。我正在尝试在同一个容器中同时运行 gunicorn(wsgi) 和 nginx 。但是我的 nginx 没有启动。通过登录容器,我可以启动 nginx。 下面是我的dockerfile


RUN apt-get clean && apt-get -y update

RUN apt-get -y install \
    nginx \
    python3-dev \
    curl \
    vim \
    build-essential \
    procps

WORKDIR /app

COPY requirements.txt /app/requirements.txt
COPY nginx-conf  /etc/nginx/sites-available/default
RUN pip install -r requirements.txt --src /usr/local/src

COPY . .

EXPOSE 8000
EXPOSE 80
CMD ["bash" , "server.sh"]

server.sh 文件看起来像


# turn on bash's job control
set -m

gunicorn  --bind  :8000  --workers 3 wsgi:app
service nginx start or /etc/init.d/nginx

gunicorn 由 server.sh 启动,但 nginx 没有启动。

我的目标是稍后在 Kubernetes 中运行这些容器。 i)我应该在单独的 pod 中同时运行 nginx 和 gunicorn 还是 ii)在具有单独容器的同一个 pod 中运行它,或者 iii)在同一个 pod 中的同一个容器中运行

【问题讨论】:

    标签: docker nginx flask gunicorn


    【解决方案1】:

    我的目标是稍后在 Kubernetes 中运行这些容器。 i) 我应该在单独的 pod 中同时运行 nginx 和 gunicorn

    是的,这个。这设置起来非常简单(考虑到有几十行“直截了当”的 YAML 文件):为 GUnicorn 后端编写一个部署和匹配(ClusterIP 类型)服务,然后编写一个单独的部署和匹配(NodePort- 或 LoadBalancer -type) Nginx 代理的服务。在 Nginx 配置中,使用 proxy_pass 指令,指向 GUnicorn Service 的名称作为后端主机名。

    这样做有几个好处。如果 Python 服务因任何原因失败,您也不必重新启动 Nginx 代理。如果您正在处理需要扩展应用程序的足够负载,则可以根据负载运行最少数量的轻量级 Nginx 代理(可能是 3 个用于冗余)和更多的后端。如果您更新应用程序,Kubernetes 将为您删除并重新创建 Deployment 管理的 Pod,同样,对代理和后端使用单独的 Deployment 意味着您无需重新启动代理,只要应用程序代码发生更改。

    所以,解决问题的第一部分:

    我正在尝试使用 gunicorn 和 nginx 部署一个 python 烧瓶应用程序。

    在普通的 Docker 中,出于类似的原因,您可以运行两个单独的容器。您可以在 Docker Compose 中管理它,它具有更简单的 YAML 文件布局;它看起来像

    version: '3.8'
    services:
      backend:
        build: . # Dockerfile just installs GUnicorn, CMD starts it
      proxy:
        image: nginx
        volumes:
          - ./nginx-conf:/etc/nginx/conf.d # could build a custom image too
            # configuration specifies `proxy_pass http://backend:8000`
        ports:
          - '8888:80'
    

    这避免了尝试让多个进程在同一个容器中运行的所有麻烦。您可以简化您显示的 Dockerfile:

    # Dockerfile
    FROM python:3.9
    RUN apt-get update \
     && DEBIAN_FRONTEND=noninteractive
        apt-get install --no-install-recommends --assume-yes \
        python3-dev \
        build-essential
    # (don't install irrelevant packages like vim or procps)
    WORKDIR /app
    COPY requirements.txt .
    RUN pip install -r requirements.txt
    COPY . .
    EXPOSE 8000
    # (don't need a shell script wrapper)
    CMD gunicorn --bind :8000 --workers 3 wsgi:app
    

    【讨论】:

      【解决方案2】:

      关于选择如何在 pod 之间拆分容器,这实际上取决于用例。如果他们彼此交谈但执行不同的任务,我会使用两个容器和一个 pod。

      另外,关于你的 server.sh 文件,gunicorn 启动但 nginx 没有启动的原因是 gunicorn 默认不以守护程序模式运行。如果你运行gunicorn --help,你会看到:

        -D, --daemon          Daemonize the Gunicorn process. [False]
      

      我仍然认为最好将容器分开,但如果您希望它正常工作,请将其更改为:

      # turn on bash's job control
      set -m
      
      gunicorn  --bind  :8000  --workers 3 wsgi:app -D
      service nginx start or /etc/init.d/nginx
      

      【讨论】:

      • 如果我运行 gunicorn --bind :8000 --workers 3 wsgi:app -D 。 docker 容器没有启动
      • 同一个文件还是多个 docker 容器?
      【解决方案3】:

      回答您关于 Kubernetes 的问题:

      这取决于你想做什么。

      同一个 Pod 中的容器共享同一个 network namespace,这意味着同一个 Pod 中的 2 个容器可以通过联系 localhost 相互通信。这意味着您的包裹永远不会被发送出去,并且始终可以进行通信。

      如果您将它们拆分为单独的 Pod,您将需要创建一个 Service object 并让它们通过该 Service 对象进行通信。将它们放在两个 Pod 中可以让您单独向上和向下扩展它们,整体上为您提供更多单独配置它们的选项,例如通过设置不同类型的安全机制。

      您选择哪个选项取决于您的架构和您想要完成的任务。 在同一个 Pod 中拥有两个容器通常只有在遵循“Sidecar”模式时才会完成,这基本上意味着有一个“主”容器在做这项工作,而 Pod 中的其他容器只是辅助“主”容器并且没有有任何理由独立存在。

      【讨论】:

        猜你喜欢
        • 2022-01-14
        • 2017-03-18
        • 1970-01-01
        • 2017-08-21
        • 1970-01-01
        • 2017-12-01
        • 2021-09-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多