如何在同一个docker容器中运行nginx和gunicorn

8cdiaqws  于 2023-06-21  发布在  Nginx
关注(0)|答案(3)|浏览(205)

我正在尝试使用gunicorn和nginx部署python flask应用程序。我试图在同一个容器中运行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由www.example.com启动server.sh,但nginx未启动。
我的目标是稍后在Kubernetes中运行这些容器。应该i)我在单独的pod中运行nginx和gunicorn,或者ii)在具有单独容器的同一pod中运行,或者iii)在同一pod中的同一容器中运行

cbjzeqam

cbjzeqam1#

我的目标是稍后在Kubernetes中运行这些容器。我应该在单独的pod中运行nginx和gunicorn吗
是的,这个。这是非常简单的设置(考虑到YAML文件有几十行“简单”):为GUnicorn后端编写一个Deployment和匹配(ClusterIP类型)Service,然后为Nginx代理编写一个单独的Deployment和匹配(NodePort或LoadBalancer类型)Service。在Nginx配置中,使用proxy_pass指令,指向GUnicorn服务的名称作为后端主机名。
这样做有几个好处。如果Python服务由于任何原因失败,您也不必重新启动Nginx代理。如果你处理的负载足够大,需要扩展应用程序,你可以运行最少数量的轻量级Nginx代理(可能是3个冗余),根据负载的不同,使用更多的后端。如果您更新应用程序,Kubernetes将为您删除并重新创建Deployment-managed Pod,并且再次为代理和后端使用单独的Deployment意味着如果仅应用程序代码更改,您不必重新启动代理。
所以,回答问题的第一部分:
我正在尝试使用gunicorn和nginx部署python flask应用程序。
在纯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
7kqas0il

7kqas0il2#

关于选择如何在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
mjqavswn

mjqavswn3#

回答您关于Kubernetes的问题:
这取决于你想做什么。
同一Pod中的容器共享同一个network namespace,即同一Pod中的2个容器可以通过联系localhost进行通信。这意味着你的包裹永远不会被发送出去,通信永远是可能的。
如果将它们分割成单独的Pod,您将需要创建一个Service object,并让它们通过该Service对象进行通信。将它们放在两个Pod中可以让您单独扩展和缩小它们,并且总体上为您提供了更多单独配置它们的选项,例如通过设置不同类型的安全机制。
选择哪一个选项取决于您的体系结构和您想要完成的任务。在同一个Pod中有两个容器通常只有在遵循“Sidecar”模式时才能做到,这基本上意味着有一个“主”容器在做工作,Pod中的其他容器只是辅助“主”容器,没有任何理由独立存在。

相关问题