nginx如何配置将不同的位置转发到不同的本地端口?
How can nginx be configured to forward different locations to different local ports?
我是 运行 docker 上的 nginx,它目前正在为一个网页提供 SSL 假设 https://example.com
我现在创建了另一组提供自己的 Web 服务器的容器,它在本地端口 8080 上可用,我希望能够在 https://example.com/new_service
中访问它
我尝试在 /new_service/ 位置添加一个简单的 proxy_pass 但我收到 502 Bad Gateway
错误并且 nginx 日志显示以下内容:
2022/04/12 22:27:12 [error] 32#32: *19 connect() failed (111: Connection refused) while connecting to upstream, client:8.8.8.8, server: example.com, request: "GET /new_service HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "example.com"
2022/04/12 22:27:12 [warn] 32#32: *19 upstream server temporarily disabled while connecting to upstream, client: 8.8.8.8, server: example.com, request: "GET /new_service/ HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "example.com"
2022/04/12 22:27:12 [error] 32#32: *19 connect() failed (111: Connection refused) while connecting to upstream, client: 8.8.8.8, server: example.com, request: "GET /new_service/ HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "example.com"
2022/04/12 22:27:12 [warn] 32#32: *19 upstream server temporarily disabled while connecting to upstream, client: 8.8.8.8, server: example.com, request: "GET /new_service/ HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "example.com"
8.8.8.8 - - [12/Apr/2022:22:27:12 +0000] "GET /new_service/ HTTP/1.1" 502 157 "-" "My Browser" "-"
我当前的配置是:
server {
listen 443;
server_name example.com;
ssl_certificate /etc/nginx/certs/example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/example.com/privkey.pem;
root /var/www/html/;
client_max_body_size 1000M; # set max upload size
fastcgi_buffers 64 4K;
index index.php;
error_page 403 /core/templates/403.php;
error_page 404 /core/templates/404.php;
add_header Strict-Transport-Security "max-age=15552000; includeSubdomains; ";
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location ~ ^/(data|config|\.ht|db_structure\.xml|README) {
deny all;
}
location ~ /(conf|bin|inc)/ {
deny all;
}
location ~ /data/ {
internal;
}
location /new_service/ {
rewrite ^/new_service/?(.*) / break;
proxy_pass http://localhost:8080/;
}
location / {
rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;
rewrite ^(/core/doc/[^\/]+/)$ /index.html;
try_files $uri $uri/ index.php;
}
location ~ ^(.+?\.php)(/.*)?$ {
try_files = 404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root;
fastcgi_param PATH_INFO ;
fastcgi_param HTTPS on;
#fastcgi_pass 127.0.0.1:9000;
fastcgi_pass php:9000;
# Or use unix-socket with 'fastcgi_pass unix:/var/run/php5-fpm.sock;'
#fastcgi_pass unix:/run/php/php7.3-fpm.sock;
}
location ~* ^.+\.(jpg|jpeg|gif|bmp|ico|png|css|js|swf)$ {
expires 30d;
# Optional: Don't log access to assets
access_log off;
}
}
我想使用 nginx 将多个位置定向到不同的本地容器一定是常见的做法,但我一直无法找到这方面的良好指导。非常感谢任何见解。
在我看来,新的 docker 容器不允许您通过它的防火墙,或者您没有将端口传递给主机
请提供 docker 配置以获得量身定制的答案。
猜测:如果你的容器不使用主机网络而是桥接网络(默认),localhost 指向 nginx 容器的本地主机而不是你的主机系统。
# Using bridge network, if omitted will be same behavior
services:
service_name:
ports:
- "8080:8080" # Portmapping, maps from Container to HOST
networks:
network_name:
networks:
network_name:
通过在主机上设置 nginx 运行 或使用 network_mode: "host"
可以访问您的服务 @ localhost:8080。但是,如果 nginx 在如上所述的容器中 运行,则 nginx 无法像那样访问此服务。 Inter-container-communication 正在使用自己的(虚拟)网络,每个容器都作为该网络中的“网络适配器”。因此有了自己的IP-Address。为了便于处理,还有一个 DNS-Server 运行,将网络别名解析为 IP。
因此使用proxy_pass http:\DNS-NAME:8080\
或proxy_pass http:\DOCKER-CONTAINER-IP:8080\
到达docker网络内的容器。使用 docker inspect CONTAINER
确定:
...
"NetworkSettings": {
"Networks": {
"NAME": {
"Aliases": [
"c4675dda79be" # <-- this
],
"IPAddress": "172.18.0.2", # <-- or that
}
别名是DNS-Names,默认使用UID,进一步可以通过
设置
docker run --net-alias
docker network connect --alias
# docker-compose:
services:
service_name: # <- this is used as an alias (=DNS-Name)
networks:
network_name:
aliases:
- alias1 # <- additional alias
由于奇怪的副作用和安全原因等原因,只要您的容器可以使用此网络隔离(默认情况下)而不是“host-mode”。因此,对于隐藏在 nginx 后面的服务,您根本不需要 port-mapping。因为它不需要在主机上发布(除了调试和开发),所以我们的服务更安全,因为 nginx 只是将东西转发到您允许的服务,而不是在给定端口上访问您的主机的所有内容。
我是 运行 docker 上的 nginx,它目前正在为一个网页提供 SSL 假设 https://example.com 我现在创建了另一组提供自己的 Web 服务器的容器,它在本地端口 8080 上可用,我希望能够在 https://example.com/new_service
中访问它我尝试在 /new_service/ 位置添加一个简单的 proxy_pass 但我收到 502 Bad Gateway
错误并且 nginx 日志显示以下内容:
2022/04/12 22:27:12 [error] 32#32: *19 connect() failed (111: Connection refused) while connecting to upstream, client:8.8.8.8, server: example.com, request: "GET /new_service HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "example.com"
2022/04/12 22:27:12 [warn] 32#32: *19 upstream server temporarily disabled while connecting to upstream, client: 8.8.8.8, server: example.com, request: "GET /new_service/ HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "example.com"
2022/04/12 22:27:12 [error] 32#32: *19 connect() failed (111: Connection refused) while connecting to upstream, client: 8.8.8.8, server: example.com, request: "GET /new_service/ HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "example.com"
2022/04/12 22:27:12 [warn] 32#32: *19 upstream server temporarily disabled while connecting to upstream, client: 8.8.8.8, server: example.com, request: "GET /new_service/ HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "example.com"
8.8.8.8 - - [12/Apr/2022:22:27:12 +0000] "GET /new_service/ HTTP/1.1" 502 157 "-" "My Browser" "-"
我当前的配置是:
server {
listen 443;
server_name example.com;
ssl_certificate /etc/nginx/certs/example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/example.com/privkey.pem;
root /var/www/html/;
client_max_body_size 1000M; # set max upload size
fastcgi_buffers 64 4K;
index index.php;
error_page 403 /core/templates/403.php;
error_page 404 /core/templates/404.php;
add_header Strict-Transport-Security "max-age=15552000; includeSubdomains; ";
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location ~ ^/(data|config|\.ht|db_structure\.xml|README) {
deny all;
}
location ~ /(conf|bin|inc)/ {
deny all;
}
location ~ /data/ {
internal;
}
location /new_service/ {
rewrite ^/new_service/?(.*) / break;
proxy_pass http://localhost:8080/;
}
location / {
rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;
rewrite ^(/core/doc/[^\/]+/)$ /index.html;
try_files $uri $uri/ index.php;
}
location ~ ^(.+?\.php)(/.*)?$ {
try_files = 404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root;
fastcgi_param PATH_INFO ;
fastcgi_param HTTPS on;
#fastcgi_pass 127.0.0.1:9000;
fastcgi_pass php:9000;
# Or use unix-socket with 'fastcgi_pass unix:/var/run/php5-fpm.sock;'
#fastcgi_pass unix:/run/php/php7.3-fpm.sock;
}
location ~* ^.+\.(jpg|jpeg|gif|bmp|ico|png|css|js|swf)$ {
expires 30d;
# Optional: Don't log access to assets
access_log off;
}
}
我想使用 nginx 将多个位置定向到不同的本地容器一定是常见的做法,但我一直无法找到这方面的良好指导。非常感谢任何见解。
在我看来,新的 docker 容器不允许您通过它的防火墙,或者您没有将端口传递给主机
请提供 docker 配置以获得量身定制的答案。 猜测:如果你的容器不使用主机网络而是桥接网络(默认),localhost 指向 nginx 容器的本地主机而不是你的主机系统。
# Using bridge network, if omitted will be same behavior
services:
service_name:
ports:
- "8080:8080" # Portmapping, maps from Container to HOST
networks:
network_name:
networks:
network_name:
通过在主机上设置 nginx 运行 或使用 network_mode: "host"
可以访问您的服务 @ localhost:8080。但是,如果 nginx 在如上所述的容器中 运行,则 nginx 无法像那样访问此服务。 Inter-container-communication 正在使用自己的(虚拟)网络,每个容器都作为该网络中的“网络适配器”。因此有了自己的IP-Address。为了便于处理,还有一个 DNS-Server 运行,将网络别名解析为 IP。
因此使用proxy_pass http:\DNS-NAME:8080\
或proxy_pass http:\DOCKER-CONTAINER-IP:8080\
到达docker网络内的容器。使用 docker inspect CONTAINER
确定:
...
"NetworkSettings": {
"Networks": {
"NAME": {
"Aliases": [
"c4675dda79be" # <-- this
],
"IPAddress": "172.18.0.2", # <-- or that
}
别名是DNS-Names,默认使用UID,进一步可以通过
设置docker run --net-alias
docker network connect --alias
# docker-compose:
services:
service_name: # <- this is used as an alias (=DNS-Name)
networks:
network_name:
aliases:
- alias1 # <- additional alias
由于奇怪的副作用和安全原因等原因,只要您的容器可以使用此网络隔离(默认情况下)而不是“host-mode”。因此,对于隐藏在 nginx 后面的服务,您根本不需要 port-mapping。因为它不需要在主机上发布(除了调试和开发),所以我们的服务更安全,因为 nginx 只是将东西转发到您允许的服务,而不是在给定端口上访问您的主机的所有内容。