使用 Angular 7、NGINX 和 Docker 刷新页面时出现 404 错误
Posted
技术标签:
【中文标题】使用 Angular 7、NGINX 和 Docker 刷新页面时出现 404 错误【英文标题】:404 Error on page refresh with Angular 7, NGINX and Docker 【发布时间】:2019-10-06 08:38:31 【问题描述】:我有一个用 Angular 7 编写的应用程序,我正在使用 nginx 将它部署到 Docker 容器中。当我运行容器时,一切正常,除了如果我在浏览器中刷新页面 (F5) 我得到 NGINX 404 错误页面。
这是我的 nginx.conf 文件,您可以从中看到我尝试过“try_files”
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events
worker_connections 1024;
http
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
gzip on;
include /etc/nginx/conf.d/*.conf;
server
listen 80;
location /
root /usr/share/nginx/html;
index index.html;
try_files $uri /index.html;
我的 Dockerfile:
FROM node:alpine as builder
RUN apk update && apk add --no-cache make git
WORKDIR /app
COPY package.json package-lock.json /app/
RUN cd /app && npm install
COPY . /app
RUN cd /app && npm run build
FROM nginx:alpine
RUN rm -rf /usr/share/nginx/html/* && rm -rf /etc/nginx/nginx.conf
COPY ./nginx.conf /etc/nginx/nginx.conf
COPY --from=builder /app/dist/hyper-client-admin /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
部署容器上的目录是:
/usr/share/nginx/html # ls -la
total 23564
drwxr-xr-x 1 root root 4096 May 20 00:18 .
drwxr-xr-x 1 root root 4096 Mar 8 03:05 ..
drwxr-xr-x 2 root root 4096 May 20 00:18 assets
-rw-r--r-- 1 root root 290728 May 20 00:18 es2015-polyfills.js
-rw-r--r-- 1 root root 211178 May 20 00:18 es2015-polyfills.js.map
-rw-r--r-- 1 root root 997 May 20 00:18 favicon.png
-rw-r--r-- 1 root root 770 May 20 00:18 index.html
-rw-r--r-- 1 root root 114749 May 20 00:18 main.js
-rw-r--r-- 1 root root 115163 May 20 00:18 main.js.map
-rw-r--r-- 1 root root 241546 May 20 00:18 polyfills.js
-rw-r--r-- 1 root root 240220 May 20 00:18 polyfills.js.map
-rw-r--r-- 1 root root 6224 May 20 00:18 runtime.js
-rw-r--r-- 1 root root 6214 May 20 00:18 runtime.js.map
-rw-r--r-- 1 root root 1117457 May 20 00:18 styles.js
-rw-r--r-- 1 root root 1191427 May 20 00:18 styles.js.map
-rw-r--r-- 1 root root 10048515 May 20 00:18 vendor.js
-rw-r--r-- 1 root root 10505601 May 20 00:18 vendor.js.map
这是控制台输出:
172.17.0.1 - - [20/May/2019:00:18:30 +0000] "GET / HTTP/1.1" 200 371 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36" "-"lopment\hyper-client-admin>
172.17.0.1 - - [20/May/2019:00:18:30 +0000] "GET /runtime.js HTTP/1.1" 200 6224 "http://localhost:81/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36" "-"
172.17.0.1 - - [20/May/2019:00:18:30 +0000] "GET /polyfills.js HTTP/1.1" 200 241546 "http://localhost:81/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36" "-"
172.17.0.1 - - [20/May/2019:00:18:30 +0000] "GET /main.js HTTP/1.1" 200 114749 "http://localhost:81/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/74.0.3729.157 Safari/537.36" "-"
172.17.0.1 - - [20/May/2019:00:18:30 +0000] "GET /styles.js HTTP/1.1" 200 1117457 "http://localhost:81/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36" "-"
172.17.0.1 - - [20/May/2019:00:18:30 +0000] "GET /vendor.js HTTP/1.1" 200 10048515 "http://localhost:81/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36" "-"
172.17.0.1 - - [20/May/2019:00:18:31 +0000] "GET /assets/logo-white.svg HTTP/1.1" 200 4519 "http://localhost:81/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/74.0.3729.157 Safari/537.36" "-"
172.17.0.1 - - [20/May/2019:00:18:31 +0000] "GET /favicon.png HTTP/1.1" 200 997 "http://localhost:81/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36" "-"
172.17.0.1 - - [20/May/2019:00:18:35 +0000] "GET /login HTTP/1.1" 404 188 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36" "-"
2019/05/20 00:18:35 [error] 6#6: *4 open() "/usr/share/nginx/html/login" failed (2: No such file or directory), client: 172.17.0.1, server: localhost, request: "GET /login HTTP/1.1", host: "localhost:81"
有什么想法吗?
更新:对此的实际答案在于@Rajesh's Answer 的cmets。问题是我正在处理 /etc/nginx/nginx.conf 并且我需要处理 /etc/nginx/conf.d/default.conf
【问题讨论】:
如果否决的选民能够澄清问题的问题以便改进,那就太好了。 【参考方案1】:我有一个经验可以补充,我最近在我的一个应用程序中遇到了这个问题,但似乎这些都不起作用,这让我偶然发现了 Nginx 在每个版本中都略有不同的记录。
在我的情况下,解决问题的原因是由于我的 nginx.conf
被写入的固有战争,/etc/nginx/conf.d/default.conf
中以下表单的 404 回退。
下面是default.conf
server
listen 80;
server_name localhost;
location /
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html =404;
index index.html index.htm;
nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events
worker_connections 1024;
http
include /etc/nginx/mime.types;
default_type application/octet-stream;
//This here takes the deafaut.conf alongside
//possibly overwriting the server markings in the nginx.conf
include /etc/nginx/conf.d/*.conf;
sendfile on;
keepalive_timeout 65;
gzip on;
server
listen 80;
server_name localhost;
location /
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html =404;
index index.html index.htm;
error_page 500 502 503 504 /50x.html;
location = /50x.html
root /usr/share/nginx/html;
您通常可以删除该行以不考虑 default.conf 或任何其他文件,这对于大多数 dockerized 容器来说都很好(但在我的情况下不是!)并且似乎适用于许多其他场景。
【讨论】:
【参考方案2】:Rajesh 的回答很棒,但我认为应该用一些代码来扩展它。
使用当前答案,例如,如果找不到 javascript 文件,则返回 index.html,这会导致浏览器将 index.html 文件缓存在您请求的 javascript 文件的名称下.如果发生这种情况,您的应用很可能会崩溃,您需要清除缓存以使其再次运行。
为了防止这种情况,您可以为 javascript 文件添加一个位置块,如果找不到该文件,它将返回 404。请参阅下面的代码。
server
listen 80;
server_name localhost;
root /usr/share/nginx/html;
# Add additional extension if you need it
location ~ \.(js)$
try_files $uri $uri/ =404;
location /
try_files $uri $uri/ /index.html;
index index.html index.htm;
注意:此示例使用 javascript 文件,但您可以使用任何文件扩展名扩展 location 块中的正则表达式,以便在找不到文件时具有 404 行为。
【讨论】:
【参考方案3】:就我而言,我有一个 NGINX 面向一组 NGINX' 作为代理,我必须添加 =404
以避免重定向循环:
location /
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html =404;
【讨论】:
【参考方案4】:这很可能可以通过简单地使用 useHash: true 标志来快速修复。由于某些未知原因,angular 不会将此设置默认为 true。
确保您的 app-routing-module.ts 文件包含这样的 useHash:
@NgModule(
imports: [RouterModule.forRoot(routes, useHash: true )],
exports: [RouterModule]
)
【讨论】:
【参考方案5】:通过刷新 Angular 应用程序,我们需要告诉 nginx Web 服务器在显示错误页面之前先查看index.html
文件是否存在请求的路由。这对我来说很好用:
server
listen 80;
server_name localhost;
location /
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
index index.html index.htm;
error_page 500 502 503 504 /50x.html;
location = /50x.html
root /usr/share/nginx/html;
【讨论】:
请看一下我的 nginx.config 文件。我已经有 try_files 了。它不起作用。请注意,我没有“文件夹”检查,但根据文档“使用 try_files 意味着您可以测试序列。如果 $uri 不存在,请尝试 $uri/,如果不存在,请尝试一个后备位置。”和“如果你不关心检查目录是否存在,你可以通过删除 $uri/ 来跳过它。” - nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls 抱歉,不确定您的评论是什么意思?什么不正确?你告诉我使用 try_files。用“try_files $uri $uri/ /index.html;”或“try_files $uri index.html;”,这两个都是正确的,我仍然有这个问题。除了说明我已经在做什么之外,您的回答没有任何目的。 让我更新答案,看看它是否有效。似乎在位置块中排序也很重要..不确定..我们可以尝试..我有这个工作..所以你可以尝试相同的位置块 刚刚得出了完全相同的结论。问题是我正在处理/etc/nginx/nginx.conf,我需要处理/etc/nginx/conf.d/default.conf 将try_files $uri $uri/ =404;
更改为 try_files $uri $uri/ /index.html;
对我有用以上是关于使用 Angular 7、NGINX 和 Docker 刷新页面时出现 404 错误的主要内容,如果未能解决你的问题,请参考以下文章
Xcode 7:Storyboard ReferenceStrong IBOutlet以及Scene Dock
Nginx 部署 Angular 前端未连接到 DRF 后端