Docker Swarm上的NGINX可在同一端口上为多个应用程序提供服务
我知道也有人问过类似的问题,但我发现的所有主题、文章和博客都无法解决我的问题。让我在这里直截了当地说: 1。我所拥有的: Docker Swarm集群(1个本地节点),NGINX作为反向代理,为了这个示例:apache、spark、rstudio和jupyter笔记本容器 2。我想要的: 我想将NGINX设置为只向主机公开一个端口(80-NGINX),并通过同一端口(80)但不同的路径通过NGINX为这4个应用程序提供服务。在我的本地开发环境中,我希望apache可以在“127.0.0.1/apache”下访问,在“127.0.0.1/rstudio”下访问rstudio,在“127.0.0.1/spark”下访问spark UI,在“127.0.0.1/jupyter”下访问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 UI无法正确渲染,因为所有css和js文件都在127.0.0.1/Spark/some.css下,但Spark UI试图从127.0.0.1/some.css中获取它们,而其他所有仪表盘基本上也是如此 在我的实际堆栈中,我有更多的服务,如色调、kafdrop等,但它们都不起作用。实际上,唯一有效的工具是apache、tomcat和rstudio。 令我惊讶的是,rstudio在身份验证、登录、注销等方面都没有问题。它完全可以。我真的不知道为什么它会起作用,当其他一切都失败了 我也试着用Traefik做同样的事情——同样的结果。使用traefik,我甚至无法设置rstudio,所有仪表板都遇到了相同的问题-无法正确加载静态内容,或者仪表板带有登录页面-错误的重定向 5。问题: 因此,我的问题是:Docker Swarm上的NGINX可在同一端口上为多个应用程序提供服务,docker,nginx,port,reverse-proxy,docker-swarm,Docker,Nginx,Port,Reverse Proxy,Docker Swarm,我知道也有人问过类似的问题,但我发现的所有主题、文章和博客都无法解决我的问题。让我在这里直截了当地说: 1。我所拥有的: Docker Swarm集群(1个本地节点),NGINX作为反向代理,为了这个示例:apache、spark、rstudio和jupyter笔记本容器 2。我想要的: 我想将NGINX设置为只向主机公开一个端口(80-NGINX),并通过同一端口(80)但不同的路径通过NGINX为这4个应用程序提供服务。在我的本地开发环境中,我希望apache可以在“127.0.0.1/ap
- 我想完成的事情可能吗
- 如果不是,为什么可以使用不同的主机名,但同一主机上的不同路径不起作用
- 如果可能的话,我应该如何设置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/;
}
}
}
此外,我创建和修改此配置所依据的材料:
我希望有人能帮助我,因为我无法解决这个问题,所以我一直在睡觉;) 我无法帮助你学习Jupyter和Spark,但希望这个答案能帮助你 如果您计划在反向代理后放置某些内容,那么应该验证它是否可以在反向代理后工作,如您所述 127.0.0.1/jupyter/tree,它将我重定向到127.0.0.1/tree 因为Jupyter的根是
/
,而不是/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配置
# /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;
}
}
docker 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
)重写规则,以切断路径,因此它将是/
(或其他)
分解器127.0.0.11有效=5s
因为您使用localhost
设置$upstream_端点jupyter:8888
因为你的通行证
代理重定向$scheme://$upstream_endpoint/$scheme://$host/jupyter/
因为你的通行证
其他一切看起来都不错。谢谢,这很有帮助。只要3个问题,如果我理解正确:1。你说我不需要我的配置的一些行,它可以被简化,但是你提到了localhost。如果我把它部署在远程服务器上,它们还能简化吗?2.所以本质上是这样的:如果一个应用程序支持可配置的根目录,那么它将在反向代理上工作,否则就没有办法让它工作了?3.可能很愚蠢,但是有没有一种方法(例如标题)可以告诉应用程序“嘿,127.0.0.1不再是你的根主机,127.0.0.1/jupyter/是你的根主机,而不是你的根主机,并且使用它”而不改变每个应用程序?1)是的,你需要删除默认的服务器并添加服务器名称。2) 不,想象一下,你有一个严格的根,/,所有链接都指向这个根,所以如果用户试图输入www.example.com/app/my_ip,这个应用程序将指向www.example.com/my_ip,但是nginx对my_ip一无所知,所以你需要向nginx添加app的所有路径,这可能是一场噩梦。3) 正如我提到的变量,是的,像X-Forwarded-For这样的变量是用来告知应用程序真正的价值的,但应用程序应该支持它。想象一下,你收集传入的ip,如果应用程序在nginx后面工作,它将始终接收nginx本地ip,因此X-Real-ip将有帮助我想知道我是否可以请你尝试坚持普通的技术写作,Dmitri。Th