运行 Docker 中的 .NET 6 项目抛出 Globalization.CultureNotFoundException

Running .NET 6 project in Docker throws Globalization.CultureNotFoundException

我已将 API 项目从 .NET 5 成功升级到 .NET 6,并且 运行在本地执行时运行良好(没有 Docker)。

我还更新了Docker文件中的版本,从“5.0-alpine3.13”更新为“6.0-alpine3.14”如下(只改变我制作)。

ARG VERSION=6.0-alpine3.14

#Runtime stage
FROM mcr.microsoft.com/dotnet/aspnet:$VERSION AS base
EXPOSE 8080
ENV DOTNET_RUNNING_IN_CONTAINER=true \
  ASPNETCORE_URLS=http://+:8080

#Build stage
FROM mcr.microsoft.com/dotnet/sdk:$VERSION AS build
WORKDIR /src
COPY ["/src/RM.Api/RM.Api.csproj", "/src/RM.Api/"]
RUN dotnet restore "/src/RM.Api/RM.Api.csproj"
COPY . .
WORKDIR "/src/src/RM.Api"

#Publish dotnet project
FROM build AS publish
ARG BUILDCONFIG=RELEASE
RUN dotnet publish "RM.Api.csproj" -c $BUILDCONFIG -o /app/publish

#Create local user, change ownership, and copy artifacts
FROM base AS final
WORKDIR /app
RUN adduser \
  --disabled-password \
  --home /app \
  --gecos '' app \
  && chown -R app /app
USER app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "RM.Api.dll"]

但是当我在 Docker 中 运行 这个 .NET 6 项目时,它会在 Startup.cs 文件中抛出下面的 Azure.Storage 异常。

这里有完整的堆栈跟踪。

Microsoft.Azure.Storage.StorageException: 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.
---> 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..ctor(String name, Boolean useUserOverride)
at Microsoft.Azure.Storage.Core.Util.AuthenticationUtility.AppendCanonicalizedCustomHeaders(CanonicalizedString canonicalizedString, HttpRequestMessage request)
at Microsoft.Azure.Storage.Core.Auth.SharedKeyCanonicalizer.CanonicalizeHttpRequest(HttpRequestMessage request, String accountName)
at Microsoft.Azure.Storage.Auth.Protocol.StorageAuthenticationHttpHandler.GetSharedKeyAuthenticationTask(StorageRequestMessage request, CancellationToken cancellationToken)
at Microsoft.Azure.Storage.Auth.Protocol.StorageAuthenticationHttpHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpMessageInvoker.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.<>n__0(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
at Microsoft.Azure.Storage.Core.Executor.Executor.ExecuteAsync[T](RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext, CancellationToken token)
--- End of inner exception stack trace ---
at Microsoft.Azure.Storage.Core.Executor.Executor.ExecuteAsync[T](RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext, CancellationToken token)
at Microsoft.Azure.Storage.Blob.CloudBlobContainer.CreateAsync(BlobContainerPublicAccessType accessType, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken)
at Microsoft.Azure.Storage.Blob.CloudBlobContainer.CreateIfNotExistsAsync(BlobContainerPublicAccessType accessType, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken)
at RM.Api.Startup.ConfigureServices(IServiceCollection services) in /src/src/RM.Api/Startup.cs:line 91

我已经更新了 Docker 文件如下,但它没有用。 有人可以帮忙吗?

ARG VERSION=6.0-alpine3.14

#Runtime stage
FROM mcr.microsoft.com/dotnet/aspnet:$VERSION AS base
EXPOSE 8080
ENV DOTNET_RUNNING_IN_CONTAINER=true \
  ASPNETCORE_URLS=http://+:8080

#Build stage
FROM mcr.microsoft.com/dotnet/sdk:$VERSION AS build
WORKDIR /src
COPY ["/src/RM.Api/RM.Api.csproj", "/src/RM.Api/"]
RUN dotnet restore "/src/RM.Api/RM.Api.csproj"
COPY . .
WORKDIR "/src/src/RM.Api"

RUN apk add --no-cache icu-libs krb5-libs libgcc libintl libssl1.1 libstdc++ zlib

ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true

#Publish dotnet project
FROM build AS publish
ARG BUILDCONFIG=RELEASE
RUN dotnet publish "RM.Api.csproj" -c $BUILDCONFIG -o /app/publish

#Create local user, change ownership, and copy artifacts
FROM base AS final
WORKDIR /app
RUN adduser \
  --disabled-password \
  --home /app \
  --gecos '' app \
  && chown -R app /app
USER app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "RM.Api.dll"]

========更新==========

进行以下两项更改解决了该问题。

  1. 更新Docker文件如下

    参数版本=6.0-alpine3.14

    #运行阶段 FROM mcr.microsoft.com/dotnet/aspnet:$VERSION 作为基础 暴露 8080 环境 DOTNET_RUNNING_IN_CONTAINER=真
    ASPNETCORE_URLS=http://+:8080 运行 apk 添加 --no-cache icu-libs krb5-libs libgcc libintl libssl1.1 libstdc++ zlib ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=假

  2. 在 .csproj 文件中添加了以下内容

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

您已将 ENV 语句放在 Dockerfile 的 'build' 部分,这意味着它不会放在最终映像中。将它放在 'base' 部分或 'final' 部分。

我会把它和其他 ENV 语句放在 'base' 部分。

如果您希望在最终映像中安装软件,您可能还想将 apk add 移动到文件的底部或最后部分。

进行以下两项更改解决了该问题。

  1. 如下更新 Dockerfile

    参数版本=6.0-alpine3.14

    #运行阶段 FROM mcr.microsoft.com/dotnet/aspnet:$VERSION 作为基础 暴露 8080

    ENV DOTNET_RUNNING_IN_CONTAINER=true
    ASPNETCORE_URLS=http://+:8080

    运行 apk 添加 --no-cache icu-libs krb5-libs libgcc libintl libssl1.1 libstdc++ zlib

    ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false

  2. 在 .csproj 文件中添加了以下内容

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

您的 docker 文件的基本部分应如下所示:

FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine AS base
WORKDIR /app
RUN apk add --no-cache icu-libs
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
EXPOSE 80
EXPOSE 443