用于在 nginx 上运行的 Angular 应用程序的 nginx 反向代理
Posted
技术标签:
【中文标题】用于在 nginx 上运行的 Angular 应用程序的 nginx 反向代理【英文标题】:nginx reverse proxy for angular app running on nginx 【发布时间】:2019-09-19 07:15:18 【问题描述】:我有一个 Docker 容器,用于在 nginx 上运行的 Angular 应用程序,名为 "website" 。我想从名为“test.nginx”的其他 nginx 反向代理容器访问这个容器。但我不知道如何为反向代理配置 nginx.conf。
首先,我正在为 Angular 应用程序创建 docker 映像。 Dockerfile:
FROM nginx:alpine
COPY default.conf /etc/nginx/conf.d/default.conf
COPY angular /usr/share/nginx/html
这里的 angular 文件夹包括 angular 构建文件(index.html, main.js, runtime.js ...)
default.conf:
server
listen 80;
server_name localhost;
location /
root /usr/share/nginx/html;
index index.html index.htm;
error_page 500 502 503 504 /50x.html;
location = /50x.html
root /usr/share/nginx/html;
docker-compose.yml
version: '3.4'
services:
nginx:
image: nginx:latest
container_name: test.nginx
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
ports:
- 2020:80
environment:
- NETWORK_ACCESS=internal
website:
image: website
container_name: website
restart: on-failure
ports:
- 2121:80
和 test.nginx 容器使用这个 nginx.conf
worker_processes 1;
events worker_connections 1024;
http
server
location /client/
proxy_pass http://website/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
当我尝试使用 http://localhost:2121 访问 Angular 应用程序时,一切都很好。 但是如果我尝试这个http://localhost:2020/client/ 我会得到这些错误
website | 192.168.208.2 - - [30/Apr/2019:15:11:18 +0000] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36" "192.168.208.1"
test.nginx | 192.168.208.1 - - [30/Apr/2019:15:11:18 +0000] "GET /client/ HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"
test.nginx | 2019/04/30 15:11:18 [error] 6#6: *5 open() "/etc/nginx/html/runtime.js" failed (2: No such file or directory), client: 192.168.208.1, server: , request: "GET /runtime.js HTTP/1.1", host: "localhost:2020", referrer: "http://localhost:2020/client/"
test.nginx | 192.168.208.1 - - [30/Apr/2019:15:11:18 +0000] "GET /runtime.js HTTP/1.1" 404 556 "http://localhost:2020/client/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"
test.nginx | 2019/04/30 15:11:18 [error] 6#6: *3 open() "/etc/nginx/html/polyfills.js" failed (2: No such file or directory), client: 192.168.208.1, server: , request: "GET /polyfills.js HTTP/1.1", host: "localhost:2020", referrer: "http://localhost:2020/client/"
test.nginx | 192.168.208.1 - - [30/Apr/2019:15:11:18 +0000] "GET /polyfills.js HTTP/1.1" 404 556 "http://localhost:2020/client/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"
test.nginx | 2019/04/30 15:11:18 [error] 6#6: *4 open() "/etc/nginx/html/styles.js" failed (2: No such file or directory), client: 192.168.208.1, server: , request: "GET /styles.js HTTP/1.1", host: "localhost:2020", referrer: "http://localhost:2020/client/"
test.nginx | 192.168.208.1 - - [30/Apr/2019:15:11:18 +0000] "GET /styles.js HTTP/1.1" 404 556 "http://localhost:2020/client/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"
test.nginx | 2019/04/30 15:11:18 [error] 6#6: *1 open() "/etc/nginx/html/vendor.js" failed (2: No such file or directory), client: 192.168.208.1, server: , request: "GET /vendor.js HTTP/1.1", host: "localhost:2020", referrer: "http://localhost:2020/client/"
test.nginx | 192.168.208.1 - - [30/Apr/2019:15:11:18 +0000] "GET /vendor.js HTTP/1.1" 404 556 "http://localhost:2020/client/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"
test.nginx | 192.168.208.1 - - [30/Apr/2019:15:11:18 +0000] "GET /main.js HTTP/1.1" 404 556 "http://localhost:2020/client/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"
test.nginx | 2019/04/30 15:11:18 [error] 6#6: *6 open() "/etc/nginx/html/main.js" failed (2: No such file or directory), client: 192.168.208.1, server: , request: "GET /main.js HTTP/1.1", host: "localhost:2020", referrer: "http://localhost:2020/client/"
当我只使用 index.html 文件而不是 angular 构建文件时,我可以从 http://localhost:2020/client/ 和 http://localhost:2121 访问 index.html 文件
请有人帮助我吗? 谢谢:)
***编辑:
我认为我收到此错误是因为 Angular 是一个单页应用程序。 现在的问题是如何为 spa 配置 location 和 proxy_pass?
【问题讨论】:
【参考方案1】:你不能只用 NGINX 和 Angular 做一个反向代理。
我们必须做的是添加 haproxy (http://www.haproxy.org/) 作为单独的服务并对其进行配置,以便它可以查看 nginx 服务器。
这个 docker 镜像可能是一个好的开始(https://hub.docker.com/_/haproxy)
对于我们的 nginx 配置,它看起来类似于:
# Api Endpoint
location /api/
proxy_pass https://api.company.com:1234/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
然后,在我们的 HA 代理中(使用 HTTPS)。我添加了一些评论来帮助指导您完成此操作。
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
user haproxy
group haproxy
daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
server=haproxy
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3
frontend server1 #Where the user is coming from (anywhere)
mode http
bind 0.0.0.0:443 ssl crt /etc/ssl/certificate.pem
acl api url_reg ^\/API/.* # Check the contents of the URL from the user's browser
use_backend api_server if api # If the ACL above is true:
# Use the api_server desription below
backend api_server # Define the api_server
mode http
server appsrv-1 10.1.1.3:443/API/ check ssl verify none
# appsrv-1 is just a title of the server.
# Use the IP to where the Backend is
# specify the port and the location. In your case
# you would use /client/
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
然后,当您完成 HA 代理配置并指向您的 nginx 服务器时,请确保您的用户首先使用其 FQDN 的 IP 地址访问 haproxy。然后,HA 代理将为您处理反向代理。
关于您关于 SPA 的问题,我的理解是您添加的 NGINX 配置内部:
proxy_pass http://api.company.com:1234/; # Where the proxy is
proxy_intercept_errors on; # IF there is a problem
error_page 404 = /index.html; # Serve the index.html as the 404 page
【讨论】:
非常感谢。您知道如何为水疗中心配置 location 和 proxy_pass 吗? @ErtuğrulGAMGAM,我更新了我的答案,将您的 SPA 问题包含在底部。我个人没有这样做,但我希望它有所帮助。 @mthola:“你不能只用 NGINX 和 Angular 做一个反向代理。”抱歉,为什么?这应该是有原因的,但我无法从你后续的回答中得到它......以上是关于用于在 nginx 上运行的 Angular 应用程序的 nginx 反向代理的主要内容,如果未能解决你的问题,请参考以下文章
Angular App 在 nginx 上运行并在附加的 nginx 反向代理后面
如何从 Angular 6 向 node.js 发送 https 请求