【问题标题】:Nginx proxy pass to dockerized gunicorn serverNginx 代理传递到 dockerized gunicorn 服务器
【发布时间】:2021-05-02 15:55:03
【问题描述】:

我尝试部署具有以下架构的应用:

  • 后端基于 dockerized Django Rest Framework,gunicorn 监听 127.0.0.1:8000
  • 前端基于 VueJS(未 dockerized)并调用我的后端 API 路由
  • NginX 用于服务前端页面并将 API 请求代理到 gunicorn

这是我的后端 docker-compose 文件的摘录:

  server:
    build:
      context: .
      dockerfile: ./docker/server/Dockerfile
    image: myserverimage
    command: 'gunicorn --bind=127.0.0.1:8000 --workers=3 my_backend.wsgi:application'
    ports:
      - 8000:8000

docker-compose up 告诉我这部分一切正常(服务器已启动,gunicorn 正在监听127.0.0.1:8000

这里是来自 nginx 配置的服务器块:

upstream backend {
                server 127.0.0.1:8000;
        }

server {
                listen 443 default_server ssl;
                server_name  mydomain.com;
                ssl_certificate /etc/nginx/ssl/nginx.crt;
                ssl_certificate_key /etc/nginx/ssl/nginx.key;

                access_log /var/log/nginx/mydomain.access.log;

                location / {
                        root   /path/to/vue/project/dist;
                        index  index.html;
                        try_files $uri $uri/ /index.html;
                }

                location /backend/ {
                        proxy_pass http://backend/;
                        proxy_http_version 1.1;
                        proxy_set_header Upgrade $http_upgrade;
                        proxy_set_header Connection "upgrade";

                        proxy_set_header Host $host;
                        proxy_set_header X-Real-IP $remote_addr;
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                        proxy_set_header X-Forwarded-Host $server_name;
                }

  }

我可以在 mydomain.com 访问我的前端页面,但对 mydomain.com/backend 的请求返回 502 bad gateway 错误。

如果我在 nginx 上游声明和 gunicorn 命令中将 127.0.0.1:8000 更改为 backend-container-ip:8000,它可以工作。

所以我的问题是:有没有办法配置这样的架构而不必知道容器 ip(我不想硬编码,尤其是在 docker-compose 声明中)? 我是否应该使用 nginx 创建一个额外的容器,即使我的前端不是基于 docker-compose 定义的?

【问题讨论】:

    标签: docker nginx docker-compose gunicorn


    【解决方案1】:

    看起来您在同一个 nginx 容器内发送请求,而不是发送到 gunicorn 容器。

    代替:

    proxy_pass http://backend/;
    

    你应该参考另一个容器

    proxy_pass http://server:8000;
    

    server 是另一个正在运行的容器的 DNS,例如在 172.17.0.2 上,可能会被 Docker compose 取代。

    【讨论】:

    • 实际上,nginx 并没有在容器中运行。我只将 docker 用于后端应用程序。但我明白你的意思,你的意思是我应该在 nginx conf 和 docker-compose gunicorn 命令中指定 docker 容器的 IP(172.17.0.2)?您不认为这是个问题吗(IP 可能会从一个安装更改为另一个)?
    • 是的,那会是个问题。 Docker compose 通过容器名称使容器可发现,参见例如docs.docker.com/compose/networking
    • 感谢您的反馈。是的,可以通过服务名称发现它们,但只能在 docker-compose 创建的默认网络中发现,对吧?就我而言,nginx 安装在主机上,不属于这个 docker-compose 网络。
    • 是的,您需要更高级的服务发现才能在 Docker compose 之外转换地址。如果您只运行单个容器,则可以使用 network: host 来绑定主机上的 gunicorn 端口 8000(除非您将该端口用于其他服务)。不建议对大量容器进行此类设置,网络不是孤立的。但是你可以从 nginx 访问127.0.0.1:8000
    • 我进一步调查了这个问题,但我不明白为什么当我可以在 127.0.0.1:5432 访问我的数据库容器时,nginx 不能以这种方式将请求代理传递到 127.0.0.1:8000 .在这两种情况下,端口实际上都是暴露的。这也不应该起作用,对吧?
    【解决方案2】:

    现在回答这个问题有点晚了,但我相信我可以解释这个问题。你有 gunicorn 监听 127.0.0.1 - localhost 或 loopback IP

    就像在 localhost 上提供的开发版本无法在您的机器外部访问一样,绑定到 localhost 的 gunicorn 也无法从容器外部访问。要解决此问题,请改为绑定到 0.0.0.0

    【讨论】:

      猜你喜欢
      • 2017-07-17
      • 2013-11-23
      • 1970-01-01
      • 2021-03-02
      • 1970-01-01
      • 2015-08-21
      • 1970-01-01
      • 2021-07-01
      • 2020-06-06
      相关资源
      最近更新 更多