如何解决使用Dockerized NGINX反向代理Dockerized REST API
请参见底部的后续操作
我是NGINX的新手,并试图为多个REST API和SPA应用程序入口点设置一个简单的内部开发Ubuntu服务器,因此我可以学习一些NGINX基础知识。
我要提供的所有API和SPA都经过了docker化处理,并且各自在localhost(Docker的主机)端口上公开其服务(用于API)或页面(用于SPA)。
例如,我在localhost:60380
有一个API,在localhost:4200
有Angular SPA应用程序,它们都在自己的Docker容器中运行。
我可以确认它们都能正常工作,因为我都可以通过基于localhost的URL来访问它们。每个API还在其URL上提供一个Swagger入口点,例如localhost:60380/swagger
(或更确切地说,localhost:60380/swagger/index.html
)。
我现在想让NGINX在localhost:80
上侦听,并根据请求的URL向每个相应的服务反向代理请求。为了保持环境整洁,NGINX也进行了泊坞化处理,即使用NGINX开源版本从容器中运行。
要对NGINX进行泊坞管理,我按照https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-docker/上的说明进行操作,即我从nginx
映像运行了一个容器,使用卷指向主机的文件夹以进行NGINX配置和静态内容。我刚刚更改了Docker命令,因为在使用文档中建议的基于安装的语法时遇到了问题(即使我指定了/
选项,看来bind
也是不允许的字符;请请注意,以下命令是从/var
执行的):
docker run --name mynginx -v $(pwd)/www:/usr/share/nginx/html:ro -v $(pwd)/nginx/conf:/etc/nginx/conf:ro -p 80:80 -d nginx
即:
- 主机
/var/www
=>容器/usr/share/nginx/html
; - 主机
/var/nginx/conf
=>/etc/nginx
。
作为测试,我在主机的文件夹中创建了两个静态网站,这些网站被映射为卷的源,即:
-
/var/www/site1
-
/var/www/site2
这两个文件夹都只有一个静态网页(index.html
)。
我在主机的/var/nginx/conf
文件夹中放置了一个nginx.conf
文件来服务这两个静态站点。这是我想出的配置:
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
# include imports configuration from a separate file.
# In this case it imports a types block,mapping each MIME type
# to a file extension,e.g.:
# types {
# text/html html htm shtml;
# text/css css;
# application/javascript js;
# ... etc
# }
include /etc/nginx/mime.types;
# the default type used if no mapping is found in types:
# here the browser will just download the file.
default_type application/octet-stream;
# log's format: the 1st parameter is the format's name (main);
# the second is a series of variables with different values
# for every request.
log_format main
'$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# path to the log file and log format's name (main,defined above).
access_log /var/log/nginx/access.log main;
# set to on: do not block on disk I/O.
sendfile on;
# keep connection alive timeout. As a page usually has a lot of assets,# this keeps the connection alive the time required to send them;
# otherwise,a new connection would be created for each asset.
keepalive_timeout 65;
# enable output compression. Recommendation is on.
gzip on;
# include all the .conf files under this folder:
include /etc/nginx/conf.d/*.conf;
}
server {
listen 80;
server_name localhost;
location /site1 {
root /usr/share/nginx/html/site1;
index index.html index.htm;
}
location /site2 {
root /usr/share/nginx/html/site2;
index index.html index.htm;
}
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
这很好,我可以从localhost/site1
和localhost/site2
浏览到这两个站点。
然后,我开始在localhost:60380
公开我的一个dockerized API。我在同一服务器块中的NGINX配置中添加了以下location
,以便在localhost/sample/api
到达它(及其在localhost/sample/api/swagger
处的招摇):
location /sample/api {
proxy_pass_header Server;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://localhost:60380;
}
由于这是ASP.NET Core Web API,因此我以https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-3.1中建议的配置作为起点。除了某些标头传递方向外,与发现的标头传递方向没有本质区别。在How to use nginx to serve a web app on a Docker container。
然后我将NGINX配置保存在主机文件夹中,并通知NGINX用docker kill -s HUP <mycontainername>
刷新它。
无论如何,虽然我仍然可以通过localhost:60380
访问API,并且两个静态站点仍然可以工作,但是访问localhost/sample/api
或localhost/sample/api/swagger
时却得到了404。 >
我尝试将proxy_redirect http://localhost:60380/ /sample/api/;
添加为建议的here,但没有任何变化。
你能建议我在做什么错吗?
更新1
我尝试将尾随/
添加到URI,但是我仍然得到404。如果这适用于Kaustubh(请参见下面的答案),那使我感到困惑,因为我仍然使用404;也许我们做了一些不同的事情。让我也回顾一下,以便像我这样的其他没有经验的读者受益:
- 准备主机:
cd /var
mkdir nginx
cd nginx
mkdir conf
cd ..
mkdir www
cd www
mkdir site1
cd ..
mkdir site2
cd ..
然后在每个文件夹index.html
,/var/www/site1
和/var/www/site2
下的下面的nginx.conf
中添加一个var/nginx/conf
页面:
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
# include imports configuration from a separate file.
# In this case it imports a types block,a new connection would be created for each asset.
keepalive_timeout 65;
# enable output compression. Recommendation is on.
gzip on;
# include all the .conf files under this folder:
include /etc/nginx/conf.d/*.conf;
}
server {
listen 80;
server_name localhost;
location /site1 {
root /usr/share/nginx/html/site1;
index index.html index.htm;
}
location /site2 {
root /usr/share/nginx/html/site2;
index index.html index.htm;
}
# https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-3.1
# https://stackoverflow.com/questions/57965728/how-to-use-nginx-to-serve-a-web-app-on-a-docker-container
# https://serverfault.com/questions/801725/nginx-config-for-restful-api-behind-proxy
location /sample/api {
# proxy_redirect http://localhost:60380/ /sample/api/;
proxy_pass_header Server;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://localhost:60380/;
}
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
-
docker run --name mynginx -v $(pwd)/www:/usr/share/nginx/html:ro -v $(pwd)/nginx/conf:/etc/nginx/conf:ro -p 80:80 -d --net=host nginx
(请注意添加的--net=host
) -
导航到
localhost/site1
和localhost/site2
:这可行。 -
从
localhost:60380
启动API(这是我的示例中的API端口)。我可以在localhost:60380
看到它的工作,在localhost:60380/swagger
看到它的摇摇欲坠的页面。 -
导航到
localhost/sample/api
:404。与localhost/sample/api/swagger/index.html
或具有此前缀的任何其他URI相同。
解决方法
我试图尽我所能复制尽可能多的内容。只有在--net=host
命令中将docker run
用于nginx之后,我才能使它工作。以下是我使用的命令。我必须使用此选项,因为nginx docker容器无法连接到我的api docker容器
$ docker run --name nginx -v $(pwd):/usr/share/nginx/html:ro -v $(pwd)/default.conf:/etc/nginx/conf.d/default.conf:ro -p 80:80 --net=host -id nginx
/etc/nginx/conf.d/default.conf
是nginx中显示Welcome to nginx page
的默认虚拟主机配置。
我将其更改为以下配置:
server {
listen 80;
server_name localhost;
# For static files
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
# For reverse_proxy
location /sample/api {
proxy_pass http://localhost:8080/;
}
}
根据此answer,端口号后应加上斜杠,以解决此问题。
我在最后进行了相同的测试,并且可以正常工作。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。