Docker Nginx代理连接上游时出现connect()失败(111: Connection refused)错误

13

我想将一个nginx容器作为所有网站和网络服务的主要入口点。我成功地运行了一个portainer容器,并且可以从互联网访问它。现在,我正在尝试访问由另一个nginx容器托管的静态网站,但是我失败了——当我访问URL时,出现错误。

502 Bad Gateway

我尝试将upstream部分添加到我的主要nginx配置中,但没有任何变化(每次更改配置后,我都会在容器内重载我的主要nginx服务)。

另一方面,如果可能的话,我希望避免添加upstream,因为生成多个不同的应用程序将需要为每个应用程序添加一个upstream - 这比我预期的要多得多。

这是我主要的nginx配置文件:

events {
    worker_connections 1024;
}
http {
    server {
        listen 80;

        location /portainer/ {
            proxy_pass http://portainer:9000/;
        }
        location /helicon/ {
            proxy_pass http://helicon:8001/;
        }
    }
}

以下是我启动主要的nginx容器的方法:

docker run -p 80:80 --name nginx -v /var/nginx/conf:/etc/nginx:ro --net=internal-net -d nginx

这是我的静态网站的 Nginx 配置文件:

events {
    worker_connections 1024;
}
http {
    server {
        listen  80;

    server_name helicon;
        root /var/www/html/helicon;

        error_log /var/log/nginx/localhost.error.log;
        access_log /var/log/nginx/localhost.access.log;
    }
}

这是用于创建和启动容器的docker-compose文件方式:

version: '3.5'
services:
    helicon:
        build: .
        image: helicon
        ports:
            - "127.0.0.1:8001:80"
        container_name: helicon
        networks:
            - internal-net
networks:
    internal-net:
        external: true

我正在使用internal-net网络来使所有应用程序保持在同一网络中,而不是使用已弃用的--link选项来运行docker

当我访问http://my.server.ip.address/helicon时,我收到502错误代码。然后我使用docker logs nginx检查日志,发现有如下信息

2018/06/24 11:15:28 [error] 848#848: *466 connect() failed (111: Connection refused) while connecting to upstream, client: Y.Y.Y.Y, server: , request: "GET /helicon/ HTTP/1.1", upstream: "http://172.18.0.2:8001/", host: "X.X.X.X"

Helicon容器确实具有IP地址172.18.0.2。

我错过了什么?也许我的方法应该完全不同于使用网络?

此致敬礼,

Daniel


在这里遇到了相同的问题,请查看此解决方案 https://dev59.com/6KXja4cB1Zd3GeqPODxN#46265221 - Espoir Murhabazi
不幸的是,这是我找到并尝试的许多“解决方案”之一-正如您所看到的,我实际上正在使用您指出的解决方案,但它并没有帮助。也许我应该做更多的事情? - Aranha
4个回答

20
若有人浏览到此页面,以下是我对 Docker 网络的理解贡献。举个例子说明,我们使用 Docker-compose 运行多个容器,例如:

  1. Docker 容器客户端
  2. Docker 容器 nginx 反向代理
  3. Docker 容器服务1
  4. Docker 容器服务2等等...

为了确保设置正确,请确认以下内容:

  1. 所有容器都在同一个网络中!
  • 首先运行: "docker network ls" 查找您堆栈的网络名称
  • 其次运行: "docker network inspect [your_stack_network_name]"
  1. 注意,在 docker-compose 中公开的端口与 nginx 反向代理无关! 这意味着您在 docker-compose 文件中公开的任何端口都可以通过浏览器从您的实际主机(即您的笔记本电脑或 PC)访问,但是为了进行代理,您必须将 nginx 指向服务的实际端口。

一步一步来:

假设服务1在容器1内的3000端口运行,您在docker-compose文件中将端口8080映射如下:"8080:3000"。使用此配置,您可以通过浏览器在本地机器上的8080端口(localhost:8080)访问容器。但是对于nginx反向代理容器来说,尝试代理到服务1时,端口8080并不相关!Docker化的nginx反向代理将使用Docker DNS将service1映射到其在Docker网络中的IP,并完全独立于您的本地主机。

对于Docker网络内的nginx反向代理,service1仅侦听3000端口!!!因此,请确保将nginx指向正确的端口!

2
您,先生,是一个传奇。 - Amdixer

15

已解决。我花了几个小时来解决这个问题,一直以为是nginx配置的问题。我不停地修改nginx.conf文件,但无法解决。我的网站一直提示502 Bad Gateway错误,并显示以下错误描述:

failed (111: Connection refused) while connecting to upstream

我找错了地方。原来我的index.js文件中的http服务器正在监听名为“localhost”的网址。

httpServer.listen(PORT, 'localhost', async err => {

这在您的开发机器上运行良好,但在容器内运行时,它必须命名为容器本身的url。我的容器已经联网,在我这种情况下,容器被命名为“backend”。

我将url从'localhost'更改为'backend',一切正常工作。

httpServer.listen(PORT, 'backend', async err => {

我浪费了几个小时在这上面,因为我完全不熟悉Node或Docker...非常感谢! - Alex Costea
它也可以与 httpServer.listen(PORT, async err => { ... } 一起使用。 - Shariful Islam Mubin
太好了!我之前在nginx里配置的是127.0.0.1而不是localhost。 - Jeff Bluemel

6
我也遇到了同样的错误。在docker-compose.yml文件中,我的服务端口被映射到了不同的端口(例如1234:8080),而我在nginx.conf文件中使用的是映射后的端口号(1234)。
然而,在docker网络中,容器不使用它们的映射端口号。为了解决这个问题,我将proxy_pass语句更改为使用正确的端口号(8080)。
为了清晰起见,正确工作的配置如下所示:(请检查nginx.conf中使用的端口号!)
docker-compose.yml
version: '3.8'

services:

...

  web1:
    ports:
      - 1234:8080
    networks:
      - net1
    
...

  proxy:
    image: nginx:latest
    networks:
      - net1

...

  networks:
    net1:
      driver: bridge

nginx.conf

... 

location /api
    ...
    proxy_pass http://web1:8080/;

我必须感谢 user8458126 指引我找到了正确的方向。


谢谢分享!正确的方式对我来说看起来很困难,所以我没有意识到这是个问题,一直使用其他/错误的端口号,但看到这个让我找到了正确的路径。 - DeltaPng

0
对我来说,我已经覆盖了我的 default.conf nginx 文件,并在我的 docker 文件中错误地输入了目标路径,这告诉 nginx 不要监听正确的端口,而是默认使用端口 80。
长话短说,确保您覆盖到正确的路径。
我原本的代码: COPY ./default.conf ./etc/nginx/default.conf 正确的代码: COPY ./default.conf ./etc/nginx/conf.d/default.conf 希望这能为某些人节省几个小时的思考时间。

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