nginx proxy_pass不适用于主机文件

时间:2019-04-02 12:53:13

标签: docker nginx docker-compose

我有这个docker-compose配置(这是我的Nginx服务的一部分)

  nginx-service:
    image: nginx:latest
    container_name: nginx-service
    command: /bin/bash -c "exec nginx -g 'daemon off;'"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/sites-enabled:/etc/nginx/sites-enabled
    restart: always
    networks:
      system-network:
        aliases:
          - nginx-service.docker
    extra_hosts:
      - serverIp:${CURRENT_SERVER_IP}
    ports:
      - 80:80
      - 443:443
      - 8081:8081

此服务器中有一个docker容器,该容器位于docker-compose网络之外,并在必要时自动创建。

我希望服务器的当前IP位于.env文件中,为此,我使用extra_hosts和此nginx配置作为代理:

server {
    listen 0.0.0.0:80;
    server_name first.example.com;

    location / {
        proxy_pass http://serverIp:8082/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

这确实有效!因为此容器始终处于打开状态,并且具有端口8082。

但是此配置不起作用,我无法修复它。你能告诉我如何解决这个问题。

server {
    listen 0.0.0.0:80;
    server_name second.example.com;
    client_max_body_size 1024m;

    location / {
        set $status_proxy 0;

        proxy_redirect     off;

        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_http_version 1.1;
        # proxy_set_header Connection "";

        proxy_connect_timeout       960s;
        proxy_send_timeout          960s;
        proxy_read_timeout          960s;
        send_timeout                960s;

        if ($cookie_testingPort ~* "(60[\d]{3})") {
            proxy_pass http://serverIp:$cookie_testingPort;
            set $status_proxy 1;
        }

        if ($status_proxy = 0) {
            return 400;
        }
    }
}

当我从second.example.com重定向时-尽管我在cookie testingPort中看到了docker容器的正确端口,但nginx返回了“ 502 Bad Gateway”,并且容器确实在服务器中具有CURRENT_SERVER_IP,这在主机文件中指定NGINX的容器

1 个答案:

答案 0 :(得分:0)

为什么它不起作用

您正在设置proxy_pass http://serverIp:$cookie_testingPort,这意味着它具有动态/可变值。当nginx具有proxy_pass的动态/可变值时,它将尝试在dns服务器的帮助下(根据传入请求)在运行时解析该域名,并且它将忽略/etc/hosts。为了使“运行时解析”起作用,您需要在nginx config中设置resolver {{ip}},并且该ip应该安装了dns服务器,但是:

  • 您不能使用resolver 127.0.0.1,因为该映像中未安装dns服务器
  • 您无法使用resolver 127.0.0.11(当前docker-compose的网络dns),因为它对serverIp一无所知

解决方案1:

  

此服务器中有一个docker容器,该容器位于docker-compose网络之外,并在必要时自动创建。

由于“外部容器”是docker容器,因此它属于某个网络。如果您设法将nginx-service容器连接到该“外部容器”的网络-您应该能够设置resolver 127.0.0.11并通过其服务名称调用“外部容器”。您可以将docker-compose之外的网络称为“外部”。 one random exampledocumentation的用法如下。

解决方案2:

您可以使用模板来生成/etc/nginx/sites-enabled/second.example.com.conf

# filename: ./second.example.com.template

server {
    listen 0.0.0.0:80;
    server_name second.example.com;

    location / {
        set $status_proxy 0;

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

        if ($cookie_testingPort ~* "(60[\d]{3})") {
            proxy_pass http://${CURRENT_SERVER_IP}:$cookie_testingPort;
            set $status_proxy 1;
        }

        if ($status_proxy = 0) {
            return 400;
        }
    }
}
# part of docker-compose.yml

  nginx-service:
    ...
    image: nginx
    volumes:
      - ./second.example.com.template:/etc/nginx/conf.d/second.example.com.template
    environment:
      - "CURRENT_SERVER_IP=${CURRENT_SERVER_IP}"
    ports:
      - 80:80
    command: /bin/bash -c "envsubst '$$CURRENT_SERVER_IP' < /etc/nginx/conf.d/second.example.com.template > /etc/nginx/conf.d/second.example.com.conf && exec nginx -g 'daemon off;'"

发生了什么事

  • 安装/etc/nginx/conf.d/second.example.com.template
  • 在容器内设置环境变量CURRENT_SERVER_IP
  • 在初始化envsubst时:
    • 读取/etc/nginx/conf.d/second.example.com.template
    • 用所需的ip替换$ CURRENT_SERVER_IP
    • 将结果另存为/etc/nginx/conf.d/second.example.com.conf
  • nginx启动