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

Docker中ASP.NET Core服务无法响应API请求求助

问题描述

使用docker-compose运行.NET 7应用时出现异常:调试日志无报错,显示应用已在对应端口运行,但访问Swagger时,虽能正常显示所有控制器端点,但发起请求后无响应,一直处于“加载”状态。

相关代码

Program.cs

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddTransient<TokenValidationMiddleware>();
builder.Services.AddHttpClient();
builder.Services.AddStackExchangeRedisCache(r =>
{
    r.Configuration = builder.Configuration["redis:connectionString"];
});

builder.Services.AddCors();
builder.Services.AddScoped<IUserContext, UserContext>();
builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
    });

builder.Services.AddDbContext<ApplicationDbContext>(options =>
{
    options.UseSqlServer(builder.Configuration.GetConnectionString("ConnectionString")).UseLazyLoadingProxies();
});

builder.Services.AddIdentityCore<ApplicationUser>(opt =>
{
    opt.Password.RequireNonAlphanumeric = false;
})
    .AddRoles<ApplicationRole>()
    .AddRoleManager<RoleManager<ApplicationRole>>()
    .AddSignInManager<SignInManager<ApplicationUser>>()
    .AddRoleValidator<RoleValidator<ApplicationRole>>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

builder.Services.AddRouting(options =>
{
    options.LowercaseUrls = true;
    options.LowercaseQueryStrings = true;
});

builder.Services.AddSingleton<SymmetricSecurityKey>(provider =>
{
    return new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!));
});

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(...
            });

builder.Services.AddAuthorization(opt =>
{
});

builder.Services.AddScoped<IDbInitializer, DbInitializer>();

builder.Services.AddAutoMapper(x => x.AddMaps(Assembly.GetExecutingAssembly()));

builder.Services.AddScoped(provider => new MapperConfiguration(cfg =>
{
    cfg.AddProfile(new AutoMapperProfiles(provider.GetService<ITokenService>()!));
}).CreateMapper());

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "web server api", Version = "v1" });
    c.SchemaFilter<EnumSchemaFilter>();
});

builder.Services.AddHttpContextAccessor();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
    app.UseCors(builder =>
    {
        builder.AllowAnyOrigin();
        builder.AllowAnyMethod();
        builder.AllowAnyHeader();
    });
}

app.UseHttpsRedirection();
app.UseRouting();

app.UseAuthentication();
app.UseMiddleware<TokenValidationMiddleware>();
app.UseAuthorization();

app.MapControllers();

using (var scope = app.Services.CreateScope())
{
    var dbInitializer = scope.ServiceProvider.GetRequiredService<IDbInitializer>();
    dbInitializer.Initialize();
}

app.Run();

DockerFile

#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["proj.csproj", "."]
RUN dotnet restore "./proj.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "proj.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "proj.csproj" -c Release -o /app/publish /p:UseAppHost=false

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "proj.dll"]

docker-compose-override.yml

version: '3.4'

services:
  tokendb:
    container_name: tokendb
    restart: always
    ports:
      - "6379:6379"
      
  db:
    container_name: sqlserver
    environment: 
      ACCEPT_EULA: 'Y'
      MSSQL_SA_PASSWORD: 'Test'
      MSSQL_PID: 'Developer'
      MSSQL_USER: 'test'
    restart: always
    ports:
      - '1433:1433'
      
  proj:
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - "ConnectionStrings__ConnectionString=Server=db;Database=db;User Id=test;Password=Test;MultipleActiveResultSets=true;TrustServerCertificate=true"
      - "redis__connectionString=tokendb"
    depends_on:
      - db
      - tokendb
    ports:
      - "8002:80"

launchsettings.json

{
  "profiles": {
    "Docker": {
      "commandName": "Docker",
      "launchBrowser": true,
      "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
      "publishAllPorts": true,
      "useSSL": true
    }
  }
}

Docker日志

warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
      Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
      No XML encryptor configured. Key {f90133af-ea02-45ca-bc10-878b34233e36} may be persisted to storage in unencrypted form.
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://[::]:80
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /app
排查与解决建议

1. 调整中间件顺序

CORS中间件位置错误,当前仅在Development块内且顺序靠后,无法正确处理跨域请求。修改请求管道顺序:

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseRouting();

// 将CORS移至此处,确保在路由之后、认证之前执行
app.UseCors(builder =>
{
    builder.AllowAnyOrigin();
    builder.AllowAnyMethod();
    builder.AllowAnyHeader();
});

app.UseAuthentication();
app.UseMiddleware<TokenValidationMiddleware>();
app.UseAuthorization();

2. 修复数据库初始化与连接问题

  • depends_on仅保证容器启动顺序,不保证SQL Server服务就绪。在DbInitializer.Initialize()中添加重试逻辑,避免初始化卡住:
public async Task Initialize()
{
    int retryCount = 5;
    var delay = TimeSpan.FromSeconds(10);
    while (retryCount > 0)
    {
        try
        {
            await _context.Database.MigrateAsync();
            // 其他初始化逻辑
            break;
        }
        catch (SqlException)
        {
            retryCount--;
            if (retryCount == 0) throw;
            await Task.Delay(delay);
        }
    }
}
  • SQL Server容器默认不会自动创建test用户,修改连接字符串使用SA账号:
- "ConnectionStrings__ConnectionString=Server=db;Database=db;User Id=sa;Password=Test;MultipleActiveResultSets=true;TrustServerCertificate=true"

3. 检查自定义中间件逻辑

确保TokenValidationMiddleware使用异步模式,避免同步阻塞请求:

public async Task InvokeAsync(HttpContext context)
{
    // 所有IO操作需使用异步方法
    await _next(context);
}

同时验证Redis连接字符串是否包含必要参数(如密码),避免连接超时。

4. 调整HTTPS配置

launchsettings.json中开启了useSSL,但容器仅映射80端口,导致HTTPS请求失败。可二选一:

  • 关闭开发环境的HTTPS重定向:
if (!app.Environment.IsDevelopment())
{
    app.UseHttpsRedirection();
}
  • 配置容器HTTPS证书并映射443端口:
proj:
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=http://+:80;https://+:443
      - ASPNETCORE_Kestrel__Certificates__Default__Password=yourcertpassword
      - ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx
    ports:
      - "8002:80"
      - "8003:443"
    volumes:
      - ${USERPROFILE}/.aspnet/https:/https:ro

5. 启用详细日志排查

在appsettings.Development.json中添加详细日志配置,查看请求过程中的隐藏异常:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Debug"
    }
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 22:05:54