Docker nginx反向代理出现"502 Bad Gateway"错误

54

我正在尝试使用nginx作为反向代理来访问其他docker容器,但在除了基础路径'/'之外的位置,我一直收到"Bad Gateway"错误。

我有以下服务器配置块:

server {

  listen 80;

  location / {
    proxy_pass "http://game2048:8080";
  }

  location /game {
    proxy_pass "http://game:9999";
  }

}

它适用于http://localhost,但不适用于http://localhost/game,在浏览器中会出现“Bad Gateway”,在nginx容器上会出现以下信息:

[error] 7#7: *6 connect() failed (111: Connection refused) 
while connecting to upstream, client: 172.17.0.1, server: , 
request: "GET /game HTTP/1.1", upstream: "http://172.17.0.4:9999/game", 
host: "localhost"

我使用官方的nginx docker镜像,并在其上放置了自己的配置。您可以在此处对其进行测试并查看所有详细信息: https://github.com/jollege/ngprox1

有什么想法是出了什么问题吗?

NB:我已经在docker主机上设置了本地主机名条目以匹配这些名称:

127.0.1.1       game2048
127.0.1.1       game

现在我发布它,我看到路径“game”被传递到上游服务器,这部分不应该被传递。有什么想法如何处理?顺便说一下,在我想要使用它的场景中,我希望它根据传入的服务器名称/HTTP标头代理到不同的服务。 - jollege
我使用了错误的端口。 - Abdus
10个回答

35

我解决了!我在nginx配置中的不同服务器块中设置了服务器名称。记得使用Docker端口,而不是主机端口。

server {

  listen 80;
  server_name game2048;

  location / {
    proxy_pass "http://game2048:8080";
  }

}

server {

  listen 80;
  server_name game;

  location / {
    # Remember to refer to docker port, not host port
    # which is 9999 in this case:
    proxy_pass "http://game:8080";
  }

}

这个 Github 仓库已更新以反映修复情况,旧的自述文件位于./README.old01.md

典型的是当我向别人仔细描述问题时,我会找到答案。你有那种感觉吗?


29
Stackoverflow非常适合使用“橡皮鸭调试法” :) - samprog
6
当然!我之前没听过这个术语,但是这个概念我真的很了解! - jollege
4
记得使用Docker端口,而不是主机端口。这帮了我大忙。谢谢。 - Alex K
请记住使用 Docker 端口,而不是主机端口。这很重要。因为使用错误的端口号,我浪费了数小时的时间。谢谢! - Tayyebi
1
对不起 @Amon,那是将近6年前的事情,我记不清了。我知道我按照上述描述使其工作正常。我不再积极使用自己的Docker容器(我使用其他人的容器)。 - jollege
显示剩余2条评论

11

我遇到了相同的"502 Bad Gateway"错误,但解决方案是根据这篇文章进行代理缓冲区大小的调整。

proxy_buffering off;
proxy_buffer_size 16k;
proxy_busy_buffers_size 24k;
proxy_buffers 64 4k;

1
如何使用Docker镜像来完成这个任务? - Roel
那正是解决我所有反向代理nginx问题的方法!非常感谢! - Genotypek

8

查看nginx错误日志

sudo tail -n 100 /var/log/nginx/error.log

如果在日志中看到像下面这样的"Permission denied"错误信息:

2022/03/28 03:51:09 [crit] 1140954#0: *141 connect() to xxx.xxx.68.xx:8080 failed (13: Permission denied) while connecting to upstream, client: xxx.xx.xxx.25, server: www.example.com

请通过运行命令sudo getsebool -a | grep httpd查看httpd_can_network_connect的值是否已启用。
如果您看到httpd_can_network_connect的值为off,那么这就是您遇到问题的原因。
解决方案: 通过运行命令sudo setsebool httpd_can_network_connect on -Phttpd_can_network_connect的值设置为on
希望这能解决您的问题。

3

对我来说,这行代码很有帮助:proxy_set_header Host $http_host;

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;
}

3

我遇到了同样的错误,但是是针对一个 Web 应用程序,它没有在配置中提到的 IP 和端口上提供服务。

所以假设你有这个:

location /game {
    proxy_pass "http://game:9999";
}

请确保您期望的Web应用程序在http://game:9999上提供服务,并且该应用程序确实是从名为“ game”的Docker容器中提供服务,代码设置为在端口9999上提供应用程序。


2
在我的情况下,经过4个小时后,我只是错过了使用semanage命令放置端口。
 location / {
            proxy_pass http://A.B.C.D:8090/test;
  }

解决方案是添加8090端口,现在可以正常工作。
semanage port -a -t http_port_t  -p tcp 8090

1
你救了我的一天!非常感谢! - Jamviet.com

0

如果您要指向另一个 docker-compose.yml 文件中定义的容器,则必须声明外部网络:

version: "3"

services:
  webserver:
    image: nginx:1.17.4-alpine
    container_name: ${PROJECT_NAME}-webserver
    depends_on:
      - drupal
    restart: unless-stopped
    ports:
      - 80:80
    volumes:
      - ./docroot:/var/www/html
      - ./nginx-conf:/etc/nginx/conf.d
      - certbot-etc:/etc/letsencrypt
    networks:
      - internal
      - my-passwords

networks:
  my-passwords:
    external: true
    name: my-passwords_default

nginx.conf:

server {
    listen          80;
    server_name     test2.com www.test2.com;
    location / {
        proxy_pass  http://my-passwords:3000/;
    }
}

0
你可能需要通过 telnet 在上游机器上检查连接是否成功: 跟踪 /var/log/nginx/error.log 可以帮助解决问题。

0
Docker 网络。 proxy_pass 需要使用 Docker 服务名称(在您的 compose.yaml 文件中定义),而不是 localhost127.0.0.10.0.0.0

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接