You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nginx负载均衡+Docker Compose下.NET Core应用无法访问问题排查

Nginx转发.NET Core Swagger无法访问的问题分析与修复

问题描述

尝试搭建Nginx负载均衡转发至两个.NET Core应用(api1、api2)的系统,应用已全环境启用Swagger和WeatherForecast端点,可通过单独URL(如http://localhost:8081/swagger/index.html)访问Swagger,但无法通过负载均衡URL(如http://localhost:81/api/api1/swagger)访问。Nginx日志显示尝试读取本地静态文件失败:

nginx  | 2025/02/26 23:49:25 [error] 32#32: *3 open() "/usr/share/nginx/html/api/api1/swagger" failed (2: No such file or directory), client: 172.19.0.1, server: localhost, request: "GET /api/api1/swagger HTTP/1.1", host: "localhost:81"
nginx  | 172.19.0.1 - - [26/Feb/2025:23:49:25 +0000] "GET /api/api1/swagger HTTP/1.1" 404 153 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:135.0) Gecko/20100101 Firefox/135.0" "-"

核心原因

  1. Nginx请求转发路径处理异常
    当前location /api/api1的配置中,proxy_pass http://api1/的结尾斜杠会替换请求路径中的/api/api1部分,但日志显示请求未被转发至后端服务,而是被Nginx当作静态文件处理,说明请求匹配逻辑未生效(可能是配置加载问题或路径匹配规则不符合预期)。同时,直接访问/swagger需要应用自动重定向到/swagger/index.html,若Nginx未传递必要头信息,重定向会失效。

  2. Swagger未适配Nginx前缀路径
    .NET Core应用不知道自身通过/api/api1前缀暴露,Swagger生成的资源路径(JS、CSS、文档地址)均以根路径/开头,浏览器会直接请求http://localhost:81/swagger/...而非http://localhost:81/api/api1/swagger/...,这些请求被Nginx当作静态文件返回404。

  3. 端口配置可能不匹配
    mcr.microsoft.com/dotnet/aspnet:8.0镜像默认监听80端口,若应用未通过代码或环境变量修改为监听8080,Docker Compose映射的8081:8080会失效,Nginx访问api1:8080会失败。

修复步骤

1. 修正Nginx配置

调整location规则并添加必要的请求头:

upstream api1 {
    server api1:8080;
}

upstream api2 {
    server api2:8080;
}

server {
    listen 80;

    location /api/api1/ {
        proxy_pass http://api1/;
        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-Proto $scheme;
    }

    location /api/api2/ {
        proxy_pass http://api2/;
        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-Proto $scheme;
    }
}
  • 给location路径添加结尾斜杠,确保匹配所有前缀请求;
  • 传递Host等头信息,让后端应用正确识别请求上下文。

2. 配置.NET Core应用的BasePath

修改Program.cs,适配Nginx的前缀路径:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// 设置应用基础路径,api2改为"/api/api2"
app.UsePathBase("/api/api1");

app.UseSwagger(c =>
{
    c.PreSerializeFilters.Add((swaggerDoc, httpReq) =>
    {
        swaggerDoc.Servers = new List<OpenApiServer> 
        { 
            new OpenApiServer { Url = $"{httpReq.Scheme}://{httpReq.Host.Value}{httpReq.PathBase}" } 
        };
    });
});

app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/api/api1/swagger/v1/swagger.json", "API1 V1");
    c.RoutePrefix = string.Empty; // 允许直接通过/api/api1访问Swagger UI
});

app.UseHttpsRedirection();

app.MapGet("/weatherforecast", () => { /* 原有逻辑 */ });

app.Run();
  • UsePathBase指定应用的访问前缀;
  • 修改Swagger配置,确保文档地址和UI路径正确适配前缀。

3. 确认应用监听端口

确保应用监听容器内的8080端口,可二选一配置:

  • 在Program.cs中添加:
    builder.WebHost.UseUrls("http://*:8080");
    
  • 或在Dockerfile中添加环境变量:
    FROM mcr.microsoft.com/dotnet/aspnet:8.0
    ENV ASPNETCORE_URLS=http://+:8080
    WORKDIR /api1
    COPY --from=build ./api1/out .
    ENTRYPOINT ["dotnet", "api1.dll"]
    

4. 重启服务

执行以下命令重新构建并启动服务:

docker-compose down
docker-compose up --build

之后可通过http://localhost:81/api/api1直接访问Swagger UI。

内容的提问来源于stack exchange,提问作者Daniele Tentoni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 04:37:35