NGINX в Docker Swarm для обслуживания нескольких приложений на одном порту - PullRequest
0 голосов
/ 17 марта 2019

Я знаю, что подобные вопросы задавались, но ни одна из найденных тем, статей и блогов не позволила мне решить мою проблему.Позвольте мне быть очень простым и конкретным здесь:

1.Что у меня есть :

Кластер Docker Swarm (1 локальный узел), NGINX в качестве обратного прокси-сервера и в качестве примера: контейнеры для ноутбуков apache, spark, rstudio и jupyter.

2.Что я хочу:

Я хочу настроить NGINX так, чтобы я мог предоставить хосту только один порт (80 - NGINX) и обслуживать эти 4 приложения через NGINX через тот же порт (80), норазные пути.В моей локальной среде разработки я хочу, чтобы apache был доступен для "127.0.0.1/apache", rstudio в "127.0.0.1/rstudio", пользовательский интерфейс spark в "127.0.0.1/spark" и jupyter в "127.0.0.1/jupyter",Все эти приложения используют разные порты внутри, это не проблема (apache - 80, spark - 8080, rstudio - 8787, jupyter - 8888).Я хочу, чтобы они использовали один и тот же порт снаружи на хосте.

3.Чего у меня нет:

У меня нет и не будет доменного имени.Мой стек должен работать, когда все, что у меня есть, это общедоступный IP-адрес сервера или нескольких принадлежащих мне серверов.Нет доменного имени.Я видел несколько примеров того, как делать то, что я хочу делать, используя имена хостов, я не хочу этого.Я хочу получить доступ к своему стеку только по IP и пути, например, 123.123.123.123/jupyter.

4.Что я придумал:

А теперь к моей актуальной проблеме - у меня есть частично работающее решение.Конкретно apache и rstudio работают нормально, а jupyter и spark - нет.Я не имею в виду, что перенаправления Jupyter вызывают проблемы.Когда я перехожу на 127.0.0.1/jupyter, меня перенаправляют на страницу входа в систему, но вместо перенаправления на 127.0.0.1/jupyter/tree он перенаправляет меня на 127.0.0.1/tree, который, конечно, не существует.Пользовательский интерфейс Spark не будет отображаться должным образом, поскольку все файлы css и js находятся под 127.0.0.1/spark/some.css, но пользовательский интерфейс spark пытается получить их из 127.0.0.1/some.css, и та же самая история в основном со всеми остальнымиинформационные панели

В моем текущем стеке у меня есть больше сервисов, таких как hue, kafdrop и т. д., и ни один из них не работает.На самом деле работают только apache, tomcat и rstudio.Я удивлен, что rstudio работает без проблем с аутентификацией, входом, выходом и т. Д. Это полностью нормально.На самом деле я понятия не имею, почему это работает, когда все остальное терпит неудачу.

Я пытался сделать то же самое с Traefik - тот же результат.С traefik я даже не смог настроить rstudio, все панели мониторинга страдали одной и той же проблемой - некорректная загрузка статического контента, или панели мониторинга со страницей входа - плохие перенаправления.

5.Вопросы:

Итак, мои вопросы:

  • - это то, что я пытаюсь сделать, даже возможно?
  • , если нет, то зачем использовать разныеимена хостов делают это возможным, но разные пути на одном хосте не работают?
  • если это возможно, то как мне настроить NGINX для правильной работы?

Моя минимальная рабочаяПример ниже: Сначала инициализируйте рой и создайте сеть:

docker swarm init


docker network create -d overlay --attachable bigdata-net

docker-compose.yml

version: '3'

services:
    nginx:
        image: nginx:alpine
        volumes:
            - ./nginx.conf:/etc/nginx/nginx.conf:ro
        ports:
            - 80:80
            - 443:443
        networks:
            - bigdata-net
        deploy:
            mode: replicated
            replicas: 1
            restart_policy:
                condition: any

    apache:
        image: httpd:alpine
        networks:
            - bigdata-net
        deploy:
            mode: replicated
            replicas: 1
            restart_policy:
                condition: any

    rstudio:
        image: rocker/rstudio:3.5.2
        networks:
            - bigdata-net
        environment:
            - PASSWORD=admin
        deploy:
            mode: replicated
            replicas: 1
            restart_policy:
                condition: any

    jupyter:
        image: jupyter/all-spark-notebook:latest
        networks:
            - bigdata-net
        deploy:
            mode: replicated
            replicas: 1
            restart_policy:
                condition: any

    spark:
        image: bde2020/spark-master:2.2.1-hadoop2.7
        networks:
            - bigdata-net
        deploy:
            mode: replicated
            replicas: 1
            restart_policy:
                condition: on-failure

nginx.conf

worker_processes auto;

events {
    worker_connections 1024; 
}

http {

    log_format compression '$remote_addr - $remote_user [$time_local] '
        '"$request" $status $upstream_addr '
        '"$http_referer" "$http_user_agent" "$gzip_ratio"';

    server {
        listen 80;
        listen [::]:80;
        access_log /var/log/nginx/access.log compression;

        ######### APACHE
        location = /apache { # without this only URL with tailing slash would work
            return 301 /apache/;
        }

        location /apache/ {
            set $upstream_endpoint apache:80;
            resolver 127.0.0.11 valid=5s;
            rewrite ^/apache(/.*) $1 break;
            proxy_pass $scheme://$upstream_endpoint;
            proxy_redirect $scheme://$upstream_endpoint/ $scheme://$host/apache/;
        }

        ######### RSTUDIO
        location = /rstudio { # without this only URL with tailing slash would work
            return 301 /rstudio/;
        }

        location /rstudio/ {
            set $upstream_endpoint rstudio:8787;
            resolver 127.0.0.11 valid=5s;
            rewrite ^/rstudio(/.*) $1 break;
            proxy_pass $scheme://$upstream_endpoint;
            proxy_redirect $scheme://$upstream_endpoint/ $scheme://$host/rstudio/;
        }

        ######### JUPYTER
        location = /jupyter { # without this only URL with tailing slash would work
            return 301 /jupyter/;
        }

        location /jupyter/ {
            set $upstream_endpoint jupyter:8888;
            resolver 127.0.0.11 valid=5s;
            rewrite ^/jupyter(/.*) $1 break;
            proxy_pass $scheme://$upstream_endpoint;
            proxy_redirect $scheme://$upstream_endpoint/ $scheme://$host/jupyter/;
        }

        ######### SPARK
        location = /spark { # without this only URL with tailing slash would work
            return 301 /spark/;
        }

        location /spark/ {
            set $upstream_endpoint spark:8080;
            resolver 127.0.0.11 valid=5s;
            rewrite ^/spark(/.*) $1 break;
            proxy_pass $scheme://$upstream_endpoint;
            proxy_redirect $scheme://$upstream_endpoint/ $scheme://$host/spark/;
        }
    }
}

Также на основе материаловна котором я создал и изменил этот конфиг: https://medium.com/@joatmon08/using-containers-to-learn-nginx-reverse-proxy-6be8ac75a757 https://community.rstudio.com/t/running-shinyapps-from-rstudio-server-behind-nginx-proxy/17706/4

Я надеюсь, что кто-то может мне помочь, у меня спит тройняшки, так как я не могу решить эту проблему;)

1 Ответ

1 голос
/ 17 марта 2019

Я не могу помочь с Jupyter и Spark, но надеюсь, что этот ответ поможет вам.

Если вы планируете разместить что-то за обратным прокси-сервером, вам следует убедиться, что оно может работать за обратным прокси-сервером, как вы упоминали.

127.0.0.1 / jupyter / tree, он перенаправляет меня на 127.0.0.1/tree

потому что для Jupyter root это /, а не /jupyter, поэтому вам нужно найти в конфигурации, как его изменить, например, для Grafana.

# The full public facing url you use in browser, used for redirects and emails
# If you use reverse proxy and sub path specify full url (with sub path)
root_url = https://example.com/grafana

Конфигурация NGINX может быть упрощена, посмотрите на этот пример:

nginx config

# /etc/nginx/conf.d/default.conf

server {
    listen 8080 default_server;

    location / {
        proxy_pass     http://echo:8080/;

        proxy_set_header X-Real-IP           $remote_addr;
        proxy_set_header X-Forwarded-Host    $host;
        proxy_set_header X-Forwarded-Port    $server_port;
        proxy_set_header X-Forwarded-Proto   $scheme;
        proxy_set_header X-Forwarded-Request $request;
        proxy_set_header X-Forwarded-Agent   $http_user_agent;
    }

    location ~ /echo([0-9]+)/ {
        rewrite ^/echo([0-9]+)(.*)$ $2 break;
        proxy_pass     http://echo:8080;

        proxy_set_header X-Real-IP           $remote_addr;
        proxy_set_header X-Forwarded-Host    $host;
        proxy_set_header X-Forwarded-Port    $server_port;
        proxy_set_header X-Forwarded-Proto   $scheme;
        proxy_set_header X-Forwarded-Request $request;
        proxy_set_header X-Forwarded-Agent   $http_user_agent;
    }
}

докер-Compose

version: "3.2"

services:
    nginx:
        image: nginx:alpine
        ports:
            - '8080:8080'
        volumes:
            - ./default.conf:/etc/nginx/conf.d/default.conf

    echo:
        image: caa06d9c/echo

тест

$ curl -L localhost:8080/echo1/

{
    "method": "GET",
    "path": "/",
    "ip": "172.31.0.1",
    "headers": {
        "X-Forwarded-Host": "localhost",
        "X-Forwarded-Port": "8080",
        "X-Forwarded-Proto": "http",
        "X-Forwarded-Agent": "curl/7.54.0",
        "X-Forwarded-Request": "GET /echo1/ HTTP/1.1"
    }
}

замечания

переменные

proxy_set_header  Host              $http_host;
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;

следует помещать на место только в том случае, если это требуется программному обеспечению, и эти имена, такие как X-Real-IP, могут отличаться, его необходимо проверить с помощью требований программного обеспечения.

Вам не нужно

переписать ^ / rstudio (/.*) $ 1 перерыв;

, поскольку nginx автоматически следует правильным правилам, вам нужно переписать правило для путей типа /path, чтобы обрезать path, так что это будет / (или что-то еще)

распознаватель 127.0.0.11 действительный = 5 с;

потому что вы используете localhost

установить $ upstream_endpoint jupyter: 8888;

из-за proxy_pass.

proxy_redirect $ схема: // $ upstream_endpoint / $ схема: // $ host / jupyter /;

из-за proxy_pass.

все остальное выглядит хорошо.

...