Nginx代理导致404未找到页面

9

我有一个运行在Docker Ubuntu镜像中的Angular应用程序,其中安装了nginx。我希望将此镜像部署到Kubernetes,并使用nginx代理将所有调用重定向到/Kubernetes中的后端服务。

我的静态Web资源位于/var/www/html中,并将以下配置添加到/etc/nginx/conf.d:

upstream backend-service {
  server backend-service:8080;
}

server {
  listen 80;

  location / {
    try_files $uri $uri/ /index.html;
  }

  location ^~ /api {
    proxy_pass http://backend-service;
  }
}

访问 / 或 /#/dashboard 的前端服务会返回我 Angular 页面的预期组件,但是对 /api/v1/data 的调用只显示默认的 nginx 404 Not Found 页面。

我需要修改什么才能使我的后端调用重定向到后端?

我使用的是 Ubuntu 16.04 上的 nginx 1.10.3,并且我的前端 Dockerfile 如下:

FROM ubuntu:16.04

# Install curl, nodejs and nginx
RUN apt-get update && \
  apt-get install -y curl && \
  curl -sL https://deb.nodesource.com/setup_8.x | bash - && \
  apt-get install -y nodejs nginx && \
  rm -rf /var/lib/apt/lists/*

# Create directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# Copy and build rest of the app
COPY . /usr/src/app
RUN npm install
RUN node_modules/@angular/cli/bin/ng build --prod
RUN cp -a dist/. /var/www/html

# Configure and start nginx
COPY frontend.conf /etc/nginx/conf.d

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

编辑:关于后端服务的信息

后端服务监听/api/v1/data上的GET和POST请求,并可以通过名为backend-service的Kubernetes服务访问

编辑2:Nginx访问日志

https://gist.github.com/Steffen911/a56e3175bf12e511048d01359a475724

172.17.0.1 - - [13/Aug/2017:13:11:40 +0000] "GET / HTTP/1.1" 200 380 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"
172.17.0.1 - - [13/Aug/2017:13:11:40 +0000] "GET /styles.d41d8cd98f00b204e980.bundle.css HTTP/1.1" 200 0 "http://192.168.99.100:30497/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"
172.17.0.1 - - [13/Aug/2017:13:11:40 +0000] "GET /inline.c9a1a6b995c65c13f605.bundle.js HTTP/1.1" 200 1447 "http://192.168.99.100:30497/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"
172.17.0.1 - - [13/Aug/2017:13:11:40 +0000] "GET /polyfills.117078cae3e3d00fc376.bundle.js HTTP/1.1" 200 97253 "http://192.168.99.100:30497/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"
172.17.0.1 - - [13/Aug/2017:13:11:40 +0000] "GET /main.3e9a37b4dd0f3bf2465f.bundle.js HTTP/1.1" 200 64481 "http://192.168.99.100:30497/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"
172.17.0.1 - - [13/Aug/2017:13:11:40 +0000] "GET /vendor.146173c1a99cc2172a5f.bundle.js HTTP/1.1" 200 661261 "http://192.168.99.100:30497/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"
172.17.0.1 - - [13/Aug/2017:13:11:40 +0000] "GET /api/v1/data/ HTTP/1.1" 404 209 "http://192.168.99.100:30497/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"
172.17.0.1 - - [13/Aug/2017:13:11:40 +0000] "GET /assets/home.jpg HTTP/1.1" 200 2608 "http://192.168.99.100:30497/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"
172.17.0.1 - - [13/Aug/2017:13:11:40 +0000] "GET /assets/busy.gif HTTP/1.1" 200 48552 "http://192.168.99.100:30497/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"
172.17.0.1 - - [13/Aug/2017:13:11:40 +0000] "GET /assets/background_light.png HTTP/1.1" 200 170599 "http://192.168.99.100:30497/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"
172.17.0.1 - - [13/Aug/2017:13:11:40 +0000] "GET /assets/google.svg HTTP/1.1" 200 2232 "http://192.168.99.100:30497/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"
172.17.0.1 - - [13/Aug/2017:13:11:40 +0000] "GET /assets/email.svg HTTP/1.1" 200 1596 "http://192.168.99.100:30497/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"
172.17.0.1 - - [13/Aug/2017:13:11:40 +0000] "GET /favicon.ico HTTP/1.1" 200 198 "http://192.168.99.100:30497/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"
172.17.0.1 - - [13/Aug/2017:13:11:44 +0000] "GET /api/v1/data/ HTTP/1.1" 404 209 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"

错误日志文件为空。

编辑3:新的nginx版本和其他SO线程

我也尝试了nginx 1.12.1,它显示相同的行为。这个问题的答案也没有帮助:nginx proxy_pass 404 error, don't understand why

编辑4:我在GitHub上上传了一个最小化的示例,可以重现我的问题

https://github.com/Steffen911/nginx-sample


你没有发布关于后端服务的任何内容?它期望什么URL?带有/api/还是没有? - Tarun Lalwani
@TarunLalwani 我更新了问题。它期望调用 /api/v1/data。 - Steffen Schmitz
请发布您的nginx日志 - Tarun Lalwani
@TarunLalwani 我已经更新了问题并附上了日志。 - Steffen Schmitz
2个回答

24
根据您对nginx的故障排除,似乎您拥有的nginx配置文件实际上没有任何效果 - 除了主页以外的所有内容都会报告404未找到错误,从location /中的try_files到更具体的location ^~/api中的proxy_pass和return 200 test等指令都没有任何效果。因此,问题似乎出现在Dockerfile中 - 大多数其他NGINX + Docker教程都会删除默认配置(例如使用RUN rm /etc/nginx/conf.d/default.conf),而您的文件则缺少此类删除。
事实上,Debian/Ubuntu 似乎有一些非标准目录,其效用可疑,分别为 /etc/nginx/sites-available/etc/nginx/sites-enabled。默认情况下,它们必须包含一个自作聪明的 listen 80 default_serverdefault 文件,有效地优先于任何其他相同端口的listen,在缺少更具体的 server_name 的情况下。
作为这样的,有多个独立的解决方案:
  • 不要使用基本上是有问题的软件包,比如Debian/Ubuntu提供的软件包。我曾经花了很长时间来摸索为什么我的配置文件不起作用,最后发现甚至像test.conf~这样的emacs备份文件也被Debian默认的include /etc/nginx/sites-enabled/*;包含在内。 Sites-Enabled很糟糕。

    请注意,NGINX为大多数发行版提供官方二进制软件包, 这样就不会出现这个问题,因为它不会尝试在其/etc/nginx/conf.d/default.conf中定义一个default_server,而是使用listen 80;server_name localhost;,在大多数情况下自动地脱离你的方式。

    例如,在你的Dockerfile中将FROM ubuntu:16.04替换为FROM nginx,以使用NGINX官方镜像。


  • 如果仍在使用来自Debian/Ubuntu的nginx,请确保在您的Dockerfile中运行RUN rm /etc/nginx/sites-enabled/default以删除default_server listen

使用server_name指令来定义基于主机名的服务器,可能与带有default_server参数的listen指令一起使用。
请注意,重复的server_name规范会导致配置警告(具有[warn]严重性),但是重复的default_server是配置错误([emerg]严重性),这可能有助于更早地排除问题。

1
天啊,点赞 * 1000。我花了很长时间才发现有一个 default.conf 服务器捕获了所有内容并忽略了我的 proxy_pass。 - Phil

7
一个调用 /api/v1/data 的请求只会显示默认的 nginx 404 Not Found 页面。 proxy_pass 指令极不可能自己生成默认的 nginx 404 Not Found 错误页面。
  • 如果404是由上游生成的,nginx将简单地传播来自上游的消息。如果您在404中获得了nginx签名,则意味着上游也在运行nginx,这可能让您感到惊讶,揭示了配置问题。

  • 如果确实是由nginx生成的404,那么可能是location不匹配的情况。尝试使用return 200 thisisatest;代替proxy_pass来解决问题。

    但是,在您的特定情况下,location ^~ /api {几乎不可能不匹配/api/v1/data/请求URI - 我能想到的唯一一件事是如果您在server配置中的任何其他location指令之外有一个try_files,这可能会使所有位置指令无效。您确定您的try_files完全包含在location /上下文中吗?


@SteffenSchmitz,哇,你能像那样重现它真的很奇怪;既然即使放置了return 200,你仍然得到404,我的唯一建议是你可能仍然有一个旧的配置文件优先于新的配置文件;就我个人而言,我曾经遇到过这样的问题,尝试修改/etc/nginx/sites-enabled中的文件,备份文件,例如test.conf~,会优先于test.conf,因此事情会变得非常奇怪。 - cnst
@SteffenSchmitz,基本上,用return 200 test替换proxy_pass并不影响你的404 Not Found结果,这几乎肯定意味着问题出在nginx配置之外的某个地方,因为它显然没有任何影响。也许你忘记在Docker中运行类似于RUN rm /etc/nginx/conf.d/default.conf的命令了? - cnst
1
@SteffenSchmitz,你的前端/etc/nginx/目录下文件的总列表是什么?似乎Debian/Ubuntu有这些愚蠢的sites-available / sites-enabled目录,其中可能有一个带有listen 80 default_serverdefault文件,很可能会优先于你的设置,因此出现404错误。 - cnst
你是对的。sites-available和sites-enabled中的默认配置覆盖了我的前端配置。我在Dockerfile中添加了RUN rm -rf /etc/nginx/sites-available和RUN rm -rf /etc/nginx/sites-enabled,后端被按预期联系上了。我还在我的conf中添加了root /var/www/html。你能否在你的答复中补充最后一条评论? - Steffen Schmitz
1
@SteffenSchmitz,太好了,我提供了一个新答案;随意接受新答案。顺便说一句,在进行赏金时,最好在7天结束前接受答案,但不要颁发赏金,因为大多数人会在最后几个小时赞同问题/答案,并且颁发赏金会使其远离此公开宣传(现在为时已晚,但对于未来而言)。 - cnst
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接