我正在使用 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
我尝试过的:
已验证后端在本地是否正常工作
https://localhost:5001
。
确认的证书已正确安装在 Docker 中。
可能是什么问题? 是我的 NGINX 配置错误,还是我需要调整 Docker 网络?如何解决 504 网关超时问题?
通常,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/
轻松访问后端。