【问题标题】:nginx docker container: 502 bad gateway responsenginx docker容器:502错误的网关响应
【发布时间】:2016-07-13 08:49:01
【问题描述】:

我有一个监听 8080 端口的服务。这不是容器。

然后,我使用官方镜像创建了一个 nginx 容器:

docker run --name nginx -d -v /root/nginx/conf:/etc/nginx/conf.d -p 443:443 -p 80:80 nginx

毕竟:

# netstat -tupln | grep 443
tcp6       0      0 :::443                  :::*                    LISTEN      3482/docker-proxy
# netstat -tupln | grep 80
tcp6       0      0 :::80                   :::*                    LISTEN      3489/docker-proxy
tcp6       0      0 :::8080                 :::*                    LISTEN      1009/java

Nginx 配置为:

upstream eighty {
    server 127.0.0.1:8080;
}

server {
    listen 80;
    server_name eighty.domain.com;

    location / {
      proxy_pass                        http://eighty;
    }
}

我已经检查了我可以使用# curl http://127.0.0.1:8080 连接到此服务器

 <html><head><meta http-equiv='refresh'
 content='1;url=/login?from=%2F'/><script>window.location.replace('/login?from=%2F');</script></head><body
 style='background-color:white; color:white;'>
 ...

它似乎运行良好,但是,当我尝试使用浏览器访问时,nginx 告诉 bt 502 bad gateway response。

我发现这可能是与非容器化进程的打开和容器之间的可见性有关的问题。我可以容器稳定连接到其他非容器进程打开的端口吗?

编辑

upstream { server 127.0.0.1:8080; }:

2016/07/13 09:06:53 [error] 5#5: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 62.57.217.25, server: eighty.domain.com, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "eighty.domain.com"
62.57.217.25 - - [13/Jul/2016:09:06:53 +0000] "GET / HTTP/1.1" 502 173 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0" "-"

upstream { server 0.0.0.0:8080; }:

62.57.217.25 - - [13/Jul/2016:09:00:30 +0000] "GET / HTTP/1.1" 502 173 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0" "-" 2016/07/13 09:00:30 [error] 5#5: *1 connect() failed (111: Connection refused) while connecting to upstream, client:
62.57.217.25, server: eighty.domain.com, request: "GET / HTTP/1.1", upstream: "http://0.0.0.0:8080/", host: "eighty.domain.com" 2016/07/13 09:00:32 [error] 5#5: *3 connect() failed (111: Connection refused) while connecting to upstream, client: 62.57.217.25, server: eighty.domain.com, request: "GET / HTTP/1.1", upstream: "http://0.0.0.0:8080/", host: "eighty.domain.com"
62.57.217.25 - - [13/Jul/2016:09:00:32 +0000] "GET / HTTP/1.1" 502 173 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0" "-"

有什么想法吗?

【问题讨论】:

  • 只是快速猜测,会不会是服务器地址的原因?您可以尝试将其从 127.0.0.1 更改为 0.0.0.0 吗?如果不是这种情况,则发生其他一些应用程序失败,检查日志或发布它们,我会尝试看看是怎么回事,还将端口(8080)添加到http://eightyproxy_pass 行。
  • 我刚刚在帖子中添加了日志。
  • 您是否也尝试过更改proxy_pass
  • 是的,我已将 proxy_pass 设置为 http://0.0.0.0:8080。同样的问题...
  • 你是在 linux 还是 windows 上使用 docker?

标签: nginx docker


【解决方案1】:

问题

Localhost 在容器方面有点棘手。在 docker 容器中,localhost 指向容器本身。 这意味着,像这样的上游:

upstream foo{
  server 127.0.0.1:8080;
}

upstream foo{
  server 0.0.0.0:8080;
}

您是在告诉 nginx 将您的请求传递给本地主机。 但是在 docker-container 的上下文中,localhost(和相应的 ip 地址)指向容器本身:

通过寻址 127.0.0.1,如果您的容器不在主机网络上,您将永远无法访问您的主机。

解决方案

主机网络

您可以选择在与您的主机相同的网络上运行 nginx:

docker run --name nginx -d -v /root/nginx/conf:/etc/nginx/conf.d --net=host nginx

请注意,在这种情况下您不需要公开任何端口。

虽然您失去了 docker 网络的好处,但这仍然有效。如果您有多个容器应该通过 docker 网络进行通信,那么这种方法可能会出现问题。如果你只是想用 docker 部署 nginx,不想使用任何高级的 docker 网络功能,这种方法很好。

访问主机远程IP地址

另一种方法是重新配置您的 nginx 上游指令以通过添加其远程 IP 地址直接连接到您的主机:

upstream foo{
  //insert your hosts ip here
  server 192.168.99.100:8080;
}

容器现在将通过网络堆栈并正确解析您的主机:

如果您有 DNS 名称,您也可以使用它。确保 docker 知道您的 DNS 服务器。

【讨论】:

  • 优秀而直接的答案。节省了我很多时间
  • 如果两者都在 kubernetes 上运行,我将如何将 nginx 连接到 docker 容器?据我了解,没有固定IP,我可以指向nginx,因为可能有多个容器实例同时运行。
  • 在这里找到了我的 kubernetes 问题的答案:stackoverflow.com/questions/50103242/…
  • 我对 192.168.*.* 的请求一直超时
  • 对于 docker-compose 你可以使用 network_mode: "host"
【解决方案2】:

对我来说帮助了这行代码proxy_set_header Host $http_host;

server {
   listen            80;
   server_name  localhost;
location / {
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header X-Forwarded-Proto $scheme;
   proxy_set_header Host $http_host;
   proxy_set_header X-NginX-Proxy true;

   proxy_redirect off;
   proxy_pass http://myserver;
}

【讨论】:

  • 我花了几天时间试图弄清楚为什么我的 nginx 容器和 docker-compose 桥接网络上的 django 容器之间的网络如此缓慢。这对我来说真的是救命稻草。谢谢。
  • 我找不到proxy_set_header X-NginX-Proxy true;的任何相关文档
【解决方案3】:

只是为了完成其他答案,我使用 mac 进行开发并直接在上游使用 host.docker.internal 为我工作,无需传递主机远程 IP 地址。这是代理nginx的配置:

events { worker_connections 1024; }

http {
    upstream app1 {
        server host.docker.internal:81;
    }

    upstream app1 {
        server host.docker.internal:82;
    }
    
    server {
        listen 80;
        server_name app1.com;
    
        location / {
          proxy_pass    http://app1;
        }
    }

    server {
        listen 80;
        server_name app2.com;
    
        location / {
          proxy_pass    http://app2;
        }
    }
}

如您所见,我为 nginx 代理后面的不同应用程序使用了不同的端口。我为 app1 使用端口 81,为 app2 使用端口 82,并且 app1 和 app2 都有自己的 nginx 容器:

对于 app1:

docker run --name nginx -d -p 81:80 nginx

对于 app2:

docker run --name nginx -d -p 82:80 nginx

另外,请参阅此链接了解更多详情: docker doc for mac

【讨论】:

    【解决方案4】:

    您可以做的是配置proxy_pass,从container 的角度来看,地址将指向您的真实主机。

    要从容器角度获取 host 地址,您可以在 Windows 上使用 docker 18.03(或更新版本)执行以下操作:

    在镜像名称为 nginx 的主机上在容器上运行 bash(适用于 Alpine Linux distribution):

     docker run -it nginx /bin/ash
    

    然后在容器内运行

    / # nslookup host.docker.internal
    
    Name:      host.docker.internal
    Address 1: 192.168.65.2
    

    192.168.65.2 是主机的 IP - 而不是像 spinus 接受的答案中的网桥 IP。

    我在这里使用host.docker.internal:

    主机有一个不断变化的 IP 地址(如果您没有网络访问权限,则没有)。从 18.03 开始​​,我们的建议是连接到特殊的 DNS 名称 host.docker.internal,它解析为主机使用的内部 IP 地址。这是出于开发目的,不适用于 Docker for Windows 之外的生产环境。

    然后您可以将nginx 配置更改为: proxy_pass http://192.168.65.2:{your_app_port};

    它应该可以正常工作。

    请记住提供与运行本地应用程序相同的port

    【讨论】:

    【解决方案5】:
    # the upstream component nginx needs to connect to
    upstream django {
    
        # server unix:///path/to/your/mysite/mysite.sock; # for a file socket
    
        server 127.0.0.1:8001; # for a web port socket (we'll use this first)
    }
    
    
    location / {
    
            uwsgi_pass  django;
            include     /path/to/your/mysite/uwsgi_params; # the uwsgi_params file you installed
        }
    

    完整参考https://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html

    【讨论】:

    • 请改进您的问题。代码+链接答案很少适合。请为您的问题添加额外的解释。我已经格式化了我认为是代码的部分答案,请检查/将其更改为您最初想要的。我现在不反对,但如果你不做这些改变,它肯定会被标记为质量非常低:(
    【解决方案6】:

    nginx.sh

    ip=$(ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | head -n 1)
    
    docker run --name nginx --add-host="host:${ip}" -p 80:80 -d nginx
    

    nginx.conf

    location / {
        ...
        proxy_pass http://host:8080/;
    }
    

    对我有用

    【讨论】:

      【解决方案7】:

      我遇到了这个问题,结果是由于权限问题导致 docker 容器无法启动。

      在我的情况下运行

      docker-compose ps 
      

      显示容器尚未启动并以状态 1 退出。原来在迁移到新机器时权限已丢失。在父目录上调整对已知员工用户的权限为我解决了这个问题,然后我能够像以前一样启动 docker 服务

      nginx_1_c18a7f6f7d6d | chown: /var/www/html: Operation not permitted
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-02-03
        • 1970-01-01
        • 1970-01-01
        • 2020-08-18
        • 1970-01-01
        • 2011-05-14
        • 2019-06-05
        • 2015-08-10
        相关资源
        最近更新 更多