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

Windows主机+Linux容器下ASP.NET Core 8 HTTPS证书问题求助

问题:Windows Docker Linux容器中ASP.NET Core 8 HTTPS认证失败

环境

  • 宿主系统:Windows
  • Docker Desktop运行Linux容器
  • ASP.NET Core 8
  • 证书生成命令:
    dotnet dev-certs https -ep %USERPROFILE%\.aspnet\https\aspnetapp.pfx -p VerySecurePassword123@!
    dotnet dev-certs https --trust
    

错误日志

dbug: Microsoft.AspNetCore.Server.Kestrel.Connections[39]
2024-11-14T02:09:35.774407159Z       Connection id "0HN84A5GB7LGC" accepted.
2024-11-14T02:09:35.774414059Z dbug: Microsoft.AspNetCore.Server.Kestrel.Connections[1]
2024-11-14T02:09:35.774430660Z       Connection id "0HN84A5GB7LGC" started.
2024-11-14T02:09:35.776304532Z dbug: Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionMiddleware[1]
2024-11-14T02:09:35.776340833Z       Failed to authenticate HTTPS connection.
2024-11-14T02:09:35.776346834Z       System.Security.Authentication.AuthenticationException: Cannot determine the frame size or a corrupted frame was received.
2024-11-14T02:09:35.776350934Z          at System.Net.Security.SslStream.GetFrameSize(ReadOnlySpan`1 buffer)
2024-11-14T02:09:35.776354134Z          at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](CancellationToken cancellationToken, Int32 estimatedSize)
2024-11-14T02:09:35.776357734Z          at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
2024-11-14T02:09:35.776362534Z          at System.Net.Security.SslStream.ReceiveHandshakeFrameAsync[TIOAdapter](CancellationToken cancellationToken)
2024-11-14T02:09:35.776365734Z          at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](Boolean receiveFirst, Byte[] reAuthenticationData, CancellationToken cancellationToken)
2024-11-14T02:09:35.776369135Z          at System.Net.Security.SslStream.ProcessAuthenticationWithTelemetryAsync(Boolean isAsync, CancellationToken cancellationToken)
2024-11-14T02:09:35.776373135Z          at Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionMiddleware.OnConnectionAsync(ConnectionContext context)
2024-11-14T02:09:35.776377135Z dbug: Microsoft.AspNetCore.Server.Kestrel.Connections[2]
2024-11-14T02:09:35.776381235Z       Connection id "0HN84A5GB7LGC" stopped.
2024-11-14T02:09:35.776534441Z dbug: Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets[7]
2024-11-14T02:09:35.776547141Z       Connection id "0HN84A5GB7LGC" sending FIN because: "The Socket transport's send loop completed gracefully."

当前配置

docker-compose.yml

services:
  pr.orderservice.webapi:
    image: pr.orderservice.webapi
    build:
      context: .
      dockerfile: OrderService/PR.OrderService.WebApi/Dockerfile
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=https://+:443;http://+:80
      - ASPNETCORE_Kestrel__Certificates__Default__Password=VerySecurePassword123@!
      - ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx
    ports:
      - "5000:80"
      - "44362:443"
    volumes:
      - ${USERPROFILE}\.aspnet\https:/https/:ro

Dockerfile

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
USER $APP_UID
WORKDIR /app
EXPOSE 8080
EXPOSE 8081

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["OrderService/PR.OrderService.WebApi/PR.OrderService.WebApi.csproj", "OrderService/PR.OrderService.WebApi/"]
COPY ["BuildingBlocks/PR.BuildingBlocks.EventBus/PR.BuildingBlocks.EventBus.csproj", "BuildingBlocks/PR.BuildingBlocks.EventBus/"]
COPY ["BuildingBlocks/PR.BuildingBlocks.Common/PR.BuildingBlocks.Common.csproj", "BuildingBlocks/PR.BuildingBlocks.Common/"]
COPY ["BuildingBlocks/PR.BuildingBlocks.Testing/PR.BuildingBlocks.Testing.csproj", "BuildingBlocks/PR.BuildingBlocks.Testing/"]
COPY ["BuildingBlocks/PR.BuildingBlocks.WebCommon/PR.BuildingBlocks.WebCommon.csproj", "BuildingBlocks/PR.BuildingBlocks.WebCommon/"]
COPY ["BuildingBlocks/PR.BuildingBlocks.CustomExceptions/PR.BuildingBlocks.CustomExceptions.csproj", "BuildingBlocks/PR.BuildingBlocks.CustomExceptions/"]
COPY ["BuildingBlocks/PR.MultiTenancyServer.AspNetCore/PR.MultiTenancyServer.AspNetCore.csproj", "BuildingBlocks/PR.MultiTenancyServer.AspNetCore/"]
COPY ["BuildingBlocks/PR.MultiTenancyServer.Core/PR.MultiTenancyServer.Core.csproj", "BuildingBlocks/PR.MultiTenancyServer.Core/"]
COPY ["OrderService/PR.OrderService.Persistence.Database/PR.OrderService.Persistence.Database.csproj", "OrderService/PR.OrderService.Persistence.Database/"]
COPY ["BuildingBlocks/PR.MultiTenancyServer.EFCore/PR.MultiTenancyServer.EFCore.csproj", "BuildingBlocks/PR.MultiTenancyServer.EFCore/"]
COPY ["BuildingBlocks/PR.MultiTenancyServer.Stores/PR.MultiTenancyServer.Stores.csproj", "BuildingBlocks/PR.MultiTenancyServer.Stores/"]
COPY ["OrderService/PR.OrderService.Domain/PR.OrderService.Domain.csproj", "OrderService/PR.OrderService.Domain/"]
COPY ["OrderService/PR.OrderService.Common/PR.OrderService.Common.csproj", "OrderService/PR.OrderService.Common/"]
COPY ["OrderService/PR.OrderService.Persistence/PR.OrderService.Persistence.csproj", "OrderService/PR.OrderService.Persistence/"]
COPY ["OrderService/PR.OrderService.Services.Resilience/PR.OrderService.Services.Resilience.csproj", "OrderService/PR.OrderService.Services.Resilience/"]
COPY ["OrderService/PR.OrderService.Services/PR.OrderService.Services.csproj", "OrderService/PR.OrderService.Services/"]
COPY ["BuildingBlocks/PR.IntegrationEvents.Commons/PR.IntegrationEvents.Commons.csproj", "BuildingBlocks/PR.IntegrationEvents.Commons/"]
RUN dotnet restore "OrderService/PR.OrderService.WebApi/PR.OrderService.WebApi.csproj"
COPY . .
WORKDIR "/src/OrderService/PR.OrderService.WebApi"
RUN dotnet build "PR.OrderService.WebApi.csproj" -c $BUILD_CONFIGURATION -o /app/build

FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "PR.OrderService.WebApi.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false

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

需求:仅需在开发环境启用HTTPS,测试NuGet包在Linux下的兼容性,对证书类型、是否带密码无要求。


解决方案

1. 统一容器暴露端口与应用监听端口

Dockerfile中EXPOSE 8080 8081与应用通过ASPNETCORE_URLS监听的80/443端口不匹配,会导致流量转发异常。修改Dockerfile的EXPOSE指令:

# 替换原EXPOSE行
EXPOSE 80
EXPOSE 443

2. 修复Linux容器内证书文件权限

Windows挂载到Linux的文件默认权限可能导致容器内非root用户($APP_UID)无法读取证书,两种解决方式:

方式一:临时切换到root用户测试(开发环境可用)

修改Dockerfile的base阶段:

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
USER root # 替换原USER $APP_UID
WORKDIR /app
EXPOSE 80
EXPOSE 443

方式二:调整挂载目录权限

在docker-compose中添加启动命令修改权限:

services:
  pr.orderservice.webapi:
    # ... 其他配置
    command: >
      sh -c "chmod -R 644 /https && dotnet PR.OrderService.WebApi.dll"

3. 验证证书挂载正确性

进入容器检查证书是否存在且完整:

# 替换<容器名>为你的容器名称或ID
docker exec -it <容器名> ls -l /https

确认aspnetapp.pfx存在,且文件大小与Windows本地文件一致。

4. 简化HTTPS配置(开发环境推荐)

若对证书无特殊要求,可让ASP.NET Core在容器内自动生成开发证书,避免跨系统挂载问题。修改docker-compose的环境变量:

environment:
  - ASPNETCORE_ENVIRONMENT=Development
  - ASPNETCORE_URLS=https://+:443;http://+:80
  # 移除原证书路径和密码配置,添加以下自动生成配置
  - ASPNETCORE_DEV_CERTIFICATE_PASSWORD=VerySecurePassword123@!

5. 检查端口映射冲突

确保宿主机器44362端口未被占用:

netstat -ano | findstr :44362

若被占用,修改docker-compose的ports映射为未使用端口,比如44363:443。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 05:59:53