nginx proxy_pass не работает с файлом hosts - PullRequest
1 голос
/ 02 апреля 2019

У меня есть эта конфигурация 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

На этом сервере есть докер-контейнер, который находится вне сети компоновки и создается автоматически при необходимости.

Я хочу, чтобы текущий 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 - nginx возвращает мне «502 Bad Gateway», хотя я вижу в cookie-тестировании порта с правильным портом для контейнера Docker, и контейнер действительно находится на сервере с CURRENT_SERVER_IP, который указан в файле hosts внутри контейнер с NGINX

1 Ответ

0 голосов
/ 04 апреля 2019

почему не работает

Вы устанавливаете proxy_pass http://serverIp:$cookie_testingPort, что означает, что оно имеет динамическое / переменное значение. Когда nginx имеет динамическое / переменное значение для proxy_pass, он пытается разрешить это доменное имя во время выполнения (по входящему запросу) с помощью DNS-сервера и игнорирует /etc/hosts. Для того, чтобы «разрешение среды выполнения» работало, вам нужно установить resolver {{ip}} в конфигурации nginx, и на этом ip должен быть установлен DNS-сервер, но:

  • вы не можете использовать resolver 127.0.0.1, потому что у вас не установлен DNS-сервер в этом образе
  • вы не можете использовать resolver 127.0.0.11 (сетевой днс текущего docker-compose), потому что он ничего не знает о serverIp

Решение 1:

На этом сервере есть Docker-контейнер, который находится вне сети Docker-compose и создается автоматически при необходимости.

Поскольку этот «внешний контейнер» является док-контейнером, он принадлежит какой-то сети. Если вам удастся подключить ваш контейнер nginx-service к сети этого "внешнего контейнера" ​​- вы сможете установить resolver 127.0.0.11 и вызывать "внешний контейнер" по имени службы. Вы можете ссылаться на сети вне docker-compose как «внешние». Вот один случайный пример о том, как это сделать, и документация .

Решение 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
  • набор env var CURRENT_SERVER_IP внутри контейнера
  • при инициализации envsubst:
    • читает /etc/nginx/conf.d/second.example.com.template
    • заменяет $ CURRENT_SERVER_IP на нужный ip
    • сохраняет результат как /etc/nginx/conf.d/second.example.com.conf
  • nginx запускается
...