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

.NET API容器部署异常:Azure DevOps构建镜像抛CultureNotFoundException

问题

我有一个.NET API,本地运行完全正常,本地构建的容器在目标机器运行也正常。但通过Azure DevOps CI构建并推送至Azure容器仓库的容器,启动后Swagger能正常运行,但调用任何接口都会抛出System.Globalization.CultureNotFoundException异常,本地构建无此问题,请问可能的问题出在哪里?


相关配置文件

Dockerfile

FROM mcr.microsoft.com/dotnet/aspnet:7.0-alpine AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
EXPOSE 5002
EXPOSE 5206
EXPOSE 7208

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

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

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

azure-pipeline.yml

trigger:
- master

resources:
- repo: self

variables:
  solution: '**/*.sln'
  buildPlatform: 'Any CPU'
  buildConfiguration: 'Release'
  # Container registry service connection established during pipeline creation
  dockerRegistryServiceConnection: 'xxxxxxxx'
  imageRepository: 'healthcheck'
  containerRegistry: 'xxxxxx'
  dockerfilePath: '$(Build.SourcesDirectory)/HealthCheck/Dockerfile'
  tag: '$(Build.BuildId)'

  # Agent VM image name
  vmImageName: 'ubuntu-latest'

stages:
- stage: BuildDocker
  displayName: Build and push stage
  jobs:
  - job: Build
    displayName: Build
    pool:
      vmImage: 'ubuntu-latest'
    steps:
    - task: Docker@2
      displayName: Build and push an image to container registry
      inputs:
        command: buildAndPush
        repository: $(imageRepository)
        dockerfile: $(dockerfilePath)
        containerRegistry: $(dockerRegistryServiceConnection)
        tags: |
          $(tag)
          latest

控制台错误信息

info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET http://192.168.10.17:5216/api/Zdarzenie/?typZdarzenia=-1 - -
info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[4]
      CORS policy execution successful.
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint 'HTTP: GET api/Zdarzenie'
fail: Microsoft.EntityFrameworkCore.Database.Connection[20004]
      An error occurred using the connection to database 'HealthCheck' on server 'xxxxxxxxxxx'.
fail: Microsoft.EntityFrameworkCore.Query[10100]
      An exception occurred while iterating over the results of a query for context type 'HealthCheck.Core.Data.ApplicationDbContext'.
      System.Globalization.CultureNotFoundException: Only the invariant culture is supported in globalization-invariant mode. See https://aka.ms/GlobalizationInvariantMode for more information. (Parameter 'name')
      en-us is an invalid culture identifier.
         at System.Globalization.CultureInfo.GetCultureInfo(String name)
         at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry, SqlConnectionOverrides overrides)
         at Microsoft.Data.SqlClient.SqlConnection.Open(SqlConnectionOverrides overrides)
         at Microsoft.Data.SqlClient.SqlConnection.Open()
         at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerConnection.OpenDbConnection(Boolean errorsExpected)
         at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternal(Boolean errorsExpected)
         at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.Open(Boolean errorsExpected)
         at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
         at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator)
         at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.<>c.<MoveNext>b__21_0(DbContext _, Enumerator enumerator)
         at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
         at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
      System.Globalization.CultureNotFoundException: Only the invariant culture is supported in globalization-invariant mode. See https://aka.ms/GlobalizationInvariantMode for more information. (Parameter 'name')
      en-us is an invalid culture identifier.
         at System.Globalization.CultureInfo.GetCultureInfo(String name)
         at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry, SqlConnectionOverrides overrides)
         at Microsoft.Data.SqlClient.SqlConnection.Open(SqlConnectionOverrides overrides)
         at Microsoft.Data.SqlClient.SqlConnection.Open()
         at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerConnection.OpenDbConnection(Boolean errorsExpected)
         at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternal(Boolean errorsExpected)
         at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.Open(Boolean errorsExpected)
         at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
         at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator)
         at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.<>c.<MoveNext>b__21_0(DbContext _, Enumerator enumerator)
         at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
         at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint 'HTTP: GET api/Zdarzenie'
fail: Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "0HMVLD3R0RJ88", Request id "0HMVLD3R0RJ88:00000002": An unhandled exception was thrown by the application.
      System.Globalization.CultureNotFoundException: Only the invariant culture is supported in globalization-invariant mode. See https://aka.ms/GlobalizationInvariantMode for more information. (Parameter 'name')
      en-us is an invalid culture identifier.
         at System.Globalization.CultureInfo.GetCultureInfo(String name)
         at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry, SqlConnectionOverrides overrides)
         at Microsoft.Data.SqlClient.SqlConnection.Open(SqlConnectionOverrides overrides)
         at Microsoft.Data.SqlClient.SqlConnection.Open()
         at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerConnection.OpenDbConnection(Boolean errorsExpected)
         at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternal(Boolean errorsExpected)
         at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.Open(Boolean errorsExpected)
         at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
         at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator)
         at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.<>c.<MoveNext>b__21_0(DbContext _, Enumerator enumerator)
         at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
         at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
         at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
         at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
         at HealthCheck.Core.Data.Repositories.ZdarzenieRepository.GetAllWithTyp(Int32 typZdarzenia, Int32 count) in /src/HealthCheck.Core/Data/Repositories/ZdarzenieRepository.cs:line 35
         at HealthCheck.API.Endpoints.ZdarzenieEndpoint.<>c.<MapZdarzenieEndpoint>b__0_0(Int32 typZdarzenia, Nullable`1 idAplikacja, IUnitOfWork unitOfWork, IMapper mapper) in /src/HealthCheck.API/Endpoints/ZdarzenieEndpoint.cs:line 20
         at lambda_method10(Closure, Object, HttpContext)
         at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)
      --- End of stack trace from previous location ---
         at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
         at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
         at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 GET http://192.168.10.17:5216/api/Zdarzenie/?typZdarzenia=-1 - - - 500 0 - 2.3359ms

原因分析

异常核心指向全球化不变模式(Globalization-Invariant Mode):

  • Alpine版本的.NET镜像默认启用该模式,目的是减小镜像体积,此时仅支持固定区域性(InvariantCulture),无法加载en-us等特定区域性
  • 本地构建时,开发环境可能隐式禁用了该模式,或系统包含完整的区域性数据,因此无异常
  • CI构建流程中,发布环节继承了Alpine镜像的全球化不变设置,且未显式关闭,导致连接数据库时加载en-us区域性失败

解决方案

1. 修改Dockerfile禁用全球化不变模式(推荐)

在base阶段添加环境变量并安装ICU区域性依赖:

FROM mcr.microsoft.com/dotnet/aspnet:7.0-alpine AS base
# 关闭全球化不变模式
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
# 安装Alpine缺失的ICU区域性数据
RUN apk add --no-cache icu-libs icu-data-full
WORKDIR /app
EXPOSE 80
EXPOSE 443
EXPOSE 5002
EXPOSE 5206
EXPOSE 7208

2. 在项目文件中禁用全球化不变模式

在API项目的.csproj文件中添加配置,强制发布时关闭该模式:

<PropertyGroup>
  <InvariantGlobalization>false</InvariantGlobalization>
</PropertyGroup>

注:若使用Alpine镜像,仍需确认是否需要额外安装ICU包,部分场景下dotnet会自动处理,但保险起见建议配合Dockerfile的依赖安装步骤。

3. 避免代码依赖特定区域性

检查EF Core/SqlClient配置,改用固定区域性:

  • 在DbContext配置中指定:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseSqlServer(connectionString, options =>
        options.UseInvariantCulture());
}
  • 或在应用启动时设置全局默认区域性:
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 23:49:50