nginx 反向代理到其他 nginx 502 坏网关

nginx reverse proxy to other nginx 502 bad gateway

我想创建两个服务,它们都有自己的 nginx。我想使用第三个 nginx 作为这两个的反向代理,但我得到了

502 Bad Gateway

当我请求时

http://127.0.0.1:8080/
http://127.0.0.1:8080/one
http://127.0.0.1:8080/two

正在访问:

http://127.0.0.1:8081
http://127.0.0.1:8082

工作正常

我有这个docker-compose.yml

version: "3.3"
services:
  nginx-one:
    image: nginx:1.17.8
    ports:
      - "8081:80"
    networks: 
      - frontend
      - backend
    volumes: 
      - ./nginx-one/html:/usr/share/nginx/html
  nginx-two:
    image: nginx:1.17.8
    ports:
      - "8082:80"
    networks: 
      - frontend
      - backend
    volumes: 
      - ./nginx-two/html:/usr/share/nginx/html
  nginx-reverse-proxy:
    image: nginx:1.17.8
    ports:
      - "8080:80"
    networks: 
      - frontend
      - backend
    volumes: 
      - ./nginx-reverse-proxy/html:/usr/share/nginx/html
      - ./nginx-reverse-proxy/conf.d:/etc/nginx/conf.d
  debian-network:
    image: cslev/debian_networking
    stdin_open: true # docker run -i
    tty: true        # docker run -t
    networks: 
      - frontend
      - backend
networks:
  frontend:
    internal: false
  backend:
    internal: true

和目录结构

.
├── docker-compose.yml
├── nginx-one
│   └── html
│       └── index.html
├── nginx-reverse-proxy
│   ├── conf.d
│   │   └── default.conf
│   └── html
│       └── index.html
├── nginx-two
    └── html
        └── index.html

nginx.conf内容

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

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

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

conf.d/default.conf

server {

    listen 80;

    location /one {
        proxy_pass http://127.0.0.1:8081/;
    }

    location /two {
        proxy_pass http://127.0.0.1:8082/;
    }
}

当我评论这行docker-compose.yml

# ./nginx-reverse-proxy/conf.d:/etc/nginx/conf.d

所以conf.d/default.conf没有用,我向楼主的浏览器请求:

http://127.0.0.1:8080/

它给出了 nginx-reverse-proxy 本身的正确响应,但显然

http://127.0.0.1:8080/one
http://127.0.0.1:8080/two

不提供来自

的任何回复
http://127.0.0.1:8081
http://127.0.0.1:8082

而是 404。

docker ps 输出:

IMAGE                     COMMAND                  CREATED          STATUS         PORTS                  NAMES
cslev/debian_networking   "bash"                   25 minutes ago   Up 3 minutes                          nginxproblem_debian-network_1
nginx:1.17.8              "nginx -g 'daemon of…"   47 minutes ago   Up 3 minutes   0.0.0.0:8080->80/tcp   nginxproblem_nginx-reverse-proxy_1
nginx:1.17.8              "nginx -g 'daemon of…"   14 hours ago     Up 3 minutes   0.0.0.0:8082->80/tcp   nginxproblem_nginx-two_1
nginx:1.17.8              "nginx -g 'daemon of…"   14 hours ago     Up 3 minutes   0.0.0.0:8081->80/tcp   nginxproblem_nginx-one_1

运行这个脚本:

#!/bin/sh

docker exec nginxproblem_debian-network_1 curl -sS 127.0.0.1:8080
docker exec nginxproblem_debian-network_1 curl -sS nginxproblem_nginx-reverse-proxy_1:8080

docker exec nginxproblem_debian-network_1 curl -sS 127.0.0.1:8080/one
docker exec nginxproblem_debian-network_1 curl -sS nginxproblem_nginx-reverse-proxy_1:8080/one
docker exec nginxproblem_debian-network_1 curl -sS 127.0.0.1:8080/two
docker exec nginxproblem_debian-network_1 curl -sS nginxproblem_nginx-reverse-proxy_1:8080/two

docker exec nginxproblem_debian-network_1 curl -sS 127.0.0.1:8081
docker exec nginxproblem_debian-network_1 curl -sS nginxproblem_nginx-one_1:8080

docker exec nginxproblem_debian-network_1 curl -sS 127.0.0.1:8082
docker exec nginxproblem_debian-network_1 curl -sS nginxproblem_nginx-two_1:8082

给出:

curl: (7) Failed to connect to 127.0.0.1 port 8080: Connection refused
curl: (7) Failed to connect to nginxproblem_nginx-reverse-proxy_1 port 8080: Connection refused
curl: (7) Failed to connect to 127.0.0.1 port 8080: Connection refused
curl: (7) Failed to connect to nginxproblem_nginx-reverse-proxy_1 port 8080: Connection refused
curl: (7) Failed to connect to 127.0.0.1 port 8080: Connection refused
curl: (7) Failed to connect to nginxproblem_nginx-reverse-proxy_1 port 8080: Connection refused
curl: (7) Failed to connect to 127.0.0.1 port 8081: Connection refused
curl: (7) Failed to connect to nginxproblem_nginx-one_1 port 8080: Connection refused
curl: (7) Failed to connect to 127.0.0.1 port 8082: Connection refused
curl: (7) Failed to connect to nginxproblem_nginx-two_1 port 8082: Connection refused

- ./nginx-reverse-proxy/conf.d:/etc/nginx/conf.d没有评论时,

与从浏览器访问 ip 地址相反,注释 - ./nginx-reverse-proxy/conf.d:/etc/nginx/conf.d 时输出相同。

除非您启用了 host networking,否则 127.0.0.1 将指向容器本身。您可以通过服务名称从同一网络中的容器内部引用其他两个容器,例如nginx-onenginx-two.

您还将容器端口 80 映射到主机上的端口 8080/8081/8082。然而,这对同一网络中容器之间的通信没有任何作用。检查 the docs:

By default, when you create or run a container using docker create or docker run, it does not publish any of its ports to the outside world. To make a port available to services outside of Docker, or to Docker containers which are not connected to the container’s network, use the --publish or -p flag. This creates a firewall rule which maps a container port to a port on the Docker host to the outside world.

所以,尝试将 http://127.0.0.1:8081/; 更改为 http://nginx-one/;,它应该可以工作。