使用Dockerized NGINX反向代理Dockerized REST API

如何解决使用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/site1localhost/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/apilocalhost/sample/api/swagger时却得到了404。 >

我尝试将proxy_redirect http://localhost:60380/ /sample/api/;添加为建议的here,但没有任何变化。

你能建议我在做什么错吗?

更新1

我尝试将尾随/添加到URI,但是我仍然得到404。如果这适用于Kaustubh(请参见下面的答案),那使我感到困惑,因为我仍然使用404;也许我们做了一些不同的事情。让我也回顾一下,以便像我这样的其他没有经验的读者受益:

  1. 准备主机:
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;
  }
}
  1. 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

  2. 导航到localhost/site1localhost/site2:这可行。

  3. localhost:60380启动API(这是我的示例中的API端口)。我可以在localhost:60380看到它的工作,在localhost:60380/swagger看到它的摇摇欲坠的页面。

  4. 导航到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 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-