如何使用 Docker 为 React 前端和 .NET 后端配置 NGINX?

问题描述 投票:0回答:1

我正在使用 Docker 在 VPS 上托管一个项目。该项目包括:

  • React 前端(Vite),

  • .NET 后端,

  • NGINX 作为反向代理。

具有文件结构:

project/
├── docker-compose.yml
├── example.client/
│   ├── dockerfile
│   └── build/   
├── example.server/
│   ├── dockerfile
│   └── app/     
└── nginx/
    ├── default.conf
    ├── nginx.conf
    └── certs
        ├── api.example.com
        │   ├── privkey.pem
        │   └── fullchain.pem 
        └── example.com
            ├── privkey.pem
            └── fullchain.pem

我希望前端在

https://example.com
上工作,后端在
https://api.example.com
上工作。两者都应使用 Let's Encrypt 的证书通过 HTTPS 提供服务。

我已经设法:

  • https://example.com
    上为前端提供服务。

我成功实现的是前端在访问 example.com 时可以工作并呈现前端的内容,但是当发出请求时,我在标头地址中看到

https://example.com/api
而不是
https://api.example.com/api
所以结果超时后是 504,这让我发疯。我相信我的 nginx 配置有问题,所以这里是我一直在使用的所有配置:

NGINX 配置:

server {
    listen 80;
    server_name example.com www.example.com;
    
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com www.example.com;
    
    ssl_certificate /etc/nginx/certs/example.com/fullchain.pem;
    ssl_certificate_key /etc/nginx/certs/example.com/privkey.pem;
    
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    location / {
        proxy_pass http://frontend:80;
        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;
    }

    location /api/ {
        proxy_pass https://api.example.com/api/; 
        proxy_set_header Host api.example.com;  
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_read_timeout 90;
        proxy_connect_timeout 90;
        proxy_send_timeout 90;
    }
    
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
}

server {
    listen 80;
    server_name api.example.com www.api.example.com;
    return 301 https://$host$request_uri; 
}

server {
    listen 443;
    server_name api.example.com;

    ssl_certificate /etc/nginx/certs/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/nginx/certs/api.example.com/privkey.pem;

    location / {
        proxy_pass https://api.example.com:5001;
        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;
    }

    error_log /var/log/nginx/api_error.log;
    access_log /var/log/nginx/api_access.log;
}

docker-compose.yml

version: '3.9'

services:
  backend:
    image: example.server
    container_name: example.server
    build:
      context: ./example.server
      dockerfile: dockerfile
    ports:
      - "5000:5000"
      - "5001:5001"
    environment:
      - ASPNETCORE_URLS=https://+:5001
      - ASPNETCORE_Kestrel__Certificates__Default__Path=/certs/fullchain.pem
      - ASPNETCORE_Kestrel__Certificates__Default__KeyPath=/certs/privkey.pem
    volumes:
    - /etc/letsencrypt/archive/api.example.com:/certs:ro
    networks:
      - app-network

  frontend:
    image: example.client
    container_name: example.client
    build:
      context: ./example.client
      dockerfile: dockerfile
    ports:
      - "3000:80"
    depends_on:
      - backend
    networks:
      - app-network
    volumes:
      - /etc/letsencrypt/archive/api.example.com:/etc/ssl/certs/api.example.com:ro
      - /etc/letsencrypt/archive/example.com:/etc/ssl/certs/example.com:ro

  nginx:
    image: nginx:latest
    container_name: nginx
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
      - ./nginx/certs/:/etc/nginx/certs:ro
    depends_on:
      - frontend
      - backend
    networks:
      - app-network


networks:
  app-network:
    driver: bridge

我尝试过的:

  1. 已验证后端在本地是否正常工作

    https://localhost:5001

  2. 确认的证书已正确安装在 Docker 中。

可能是什么问题? 是我的 NGINX 配置错误,还是我需要调整 Docker 网络?如何解决 504 网关超时问题?

nginx vps
1个回答
0
投票

通常,SSL 终止由 nginx-reverse-proxy 处理。所以后端不应该知道证书。

记住这一点,你的 nginx 配置应该如下所示:

server {
    listen 80;
    server_name example.com www.example.com;
    
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com www.example.com;
    
    ssl_certificate /etc/nginx/certs/example.com/fullchain.pem;
    ssl_certificate_key /etc/nginx/certs/example.com/privkey.pem;
    
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    location / {
        proxy_pass http://frontend:80;
        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;
    }

    location /api/ {
        proxy_pass http://backend:5000/api/;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_read_timeout 90;
        proxy_connect_timeout 90;
        proxy_send_timeout 90;
    }
    
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
}

在您的前端,您现在可以通过

/api/
轻松访问后端。

© www.soinside.com 2019 - 2024. All rights reserved.