Assume the following program. It's a simple, quite empty command line application with hosting, logging and lamar configured.
When running .NET 6 in an Alpine docker container, by default, the globalization invariant mode is active. You can read more about the topic here.
Update: Any .net 6 docker runtime has this mode now preconfigured. This is a breaking change in .net 6.
Program.cs
using Lamar;
using Lamar.Microsoft.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Events;
using Serilog.Settings.Configuration;
namespace MyApp;
public static class Program
{
public static async Task<int> Main(string[] args)
{
Log.Logger = SetupDefaultLoggerConfiguration(new LoggerConfiguration()).CreateBootstrapLogger();
try
{
return await CreateHostBuilder().RunCommandLineApplicationAsync<App>(args);
}
catch (Exception ex)
{
Log.Fatal(ex, "An error occurred: {Error}", ex.Message);
return 1;
}
finally
{
Log.CloseAndFlush();
}
}
private static void ConfigureApp(HostBuilderContext host, IConfigurationBuilder config)
{
config.AddJsonFile("appsettings.json", optional: true)
.AddEnvironmentVariables();
}
private static void ConfigureContainer(HostBuilderContext host, ServiceRegistry services)
{
services.Scan(scan =>
{
scan.TheCallingAssembly();
scan.WithDefaultConventions(ServiceLifetime.Transient);
});
}
private static void ConfigureLogger(HostBuilderContext host, LoggerConfiguration config)
{
SetupDefaultLoggerConfiguration(config).ReadFrom.Configuration(host.Configuration,
nameof(Serilog),
ConfigurationAssemblySource.UseLoadedAssemblies);
}
private static LoggerConfiguration SetupDefaultLoggerConfiguration(LoggerConfiguration configuration) =>
configuration
.MinimumLevel.Verbose()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.Enrich.FromLogContext()
.WriteTo.Console();
private static IHostBuilder CreateHostBuilder() => new HostBuilder()
.ConfigureAppConfiguration(ConfigureApp)
.UseLamar(ConfigureContainer)
.UseSerilog(ConfigureLogger);
}
Dockerfile
FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build
WORKDIR /app
COPY ./*.csproj /app/
RUN dotnet restore
FROM build as publish
WORKDIR /app
COPY . .
RUN dotnet publish . -c Release -o /app/.dist
FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine AS runtime
WORKDIR /app
COPY --from=publish /app/.dist /app/
ENTRYPOINT ["/app/MyApp"]
Expected Behaviour
The expected behaviour is, that the application runs as usual and successfully registers all services matching the assembly scanner.
Actual Behaviour
The application immediately crashes on assembly scanning. See the following stacktrace for more information:
Exception thrown: 'System.Globalization.CultureNotFoundException' in System.Private.CoreLib.dll
An exception of type 'System.Globalization.CultureNotFoundException' occurred in System.Private.CoreLib.dll but was not handled in user code: 'Only the invariant culture is supported in globalization-invariant mode. See https://aka.ms/GlobalizationInvariantMode for more information.'
Stack trace:
> at System.Globalization.CultureInfo..ctor(String name, Boolean useUserOverride)
> at BaselineTypeDiscovery.CallingAssembly.GetStackTraceInEnglish()
> at BaselineTypeDiscovery.CallingAssembly.Find()
> at Lamar.Scanning.Conventions.AssemblyScanner.TheCallingAssembly()
> at MyApp.Program.<>c.<ConfigureContainer>b__2_0(IAssemblyScanner scan) in C:\code\MyApp\Program.cs:line 42
> at Lamar.ServiceRegistry.Scan(Action`1 scan)
> at MyApp.Program.ConfigureContainer(HostBuilderContext host, ServiceRegistry services) in C:\code\MyApp\Program.cs:line 40
> at Lamar.Microsoft.DependencyInjection.HostBuilderExtensions.<>c__DisplayClass1_0.<UseLamar>b__0(HostBuilderContext context, IServiceCollection services)
> at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
> at Microsoft.Extensions.Hosting.HostBuilder.Build()
> at Microsoft.Extensions.Hosting.HostBuilderExtensions.<RunCommandLineApplicationAsync>d__1`1.MoveNext()
C# Version: 10.0 .NET: 6.0.9 Lamar: 8.0.1 Docker: mcr.microsoft.com/dotnet/aspnet:6.0-alpine
Description
Assume the following program. It's a simple, quite empty command line application with hosting, logging and lamar configured.
When running .NET 6 in an Alpine docker container, by default, the globalization invariant mode is active. You can read more about the topic here.
Update: Any .net 6 docker runtime has this mode now preconfigured. This is a breaking change in .net 6.
Program.cs
Dockerfile
Expected Behaviour
The expected behaviour is, that the application runs as usual and successfully registers all services matching the assembly scanner.
Actual Behaviour
The application immediately crashes on assembly scanning. See the following stacktrace for more information: