ci(build): target .NET 10 Alpine with low-memory tuning
Some checks failed
Caddy Manager CI build / docker (push) Failing after 32s

This commit is contained in:
2026-07-26 16:15:00 +07:00
parent 7380680230
commit 96f0112449
7 changed files with 43 additions and 6 deletions

View File

@@ -25,7 +25,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v3
with:
dotnet-version: '9' # SDK Version to use.
dotnet-version: '10' # SDK Version to use.
dotnet-quality: 'ga'
cache: true
cache-dependency-path: '**/packages.lock.json'
@@ -42,6 +42,6 @@ jobs:
- name: Publish container
run: |
dotnet publish \
--configuration Release --os linux --arch x64 \
--configuration Release --os linux-musl --arch x64 \
/t:PublishContainer -p ContainerRegistry=ghcr.io \
-p ContainerRepository=${{ github.repository }} -p:ContainerImageTags='"${{ steps.metadata.outputs.APP_VERSION }};latest"'

View File

@@ -10,8 +10,23 @@
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<!-- To avoid error on lock file not found -->
<DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>
<!--
Low-traffic single-user admin UI: trade GC throughput for a much smaller heap.
Server GC (the Web SDK default) reserves one heap per CPU core.
-->
<ServerGarbageCollection>false</ServerGarbageCollection>
<ConcurrentGarbageCollection>false</ConcurrentGarbageCollection>
<TieredPGO>false</TieredPGO>
<!-- No localized content, so skip loading ICU entirely (alpine ships no ICU anyway) -->
<InvariantGlobalization>true</InvariantGlobalization>
<ContainerBaseImage>mcr.microsoft.com/dotnet/aspnet:10.0-alpine</ContainerBaseImage>
</PropertyGroup>
<ItemGroup>
<!-- No MSBuild property exists for this one; lands in runtimeconfig.json for both build paths -->
<RuntimeHostConfigurationOption Include="System.GC.ConserveMemory" Value="9" />
</ItemGroup>
<ItemGroup>
<Content Include="..\.dockerignore">
<Link>.dockerignore</Link>

View File

@@ -1,4 +1,4 @@
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base
FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS base
USER $APP_UID
WORKDIR /app
EXPOSE 8080

View File

@@ -1,4 +1,5 @@
using CaddyManager.Components;
using Microsoft.AspNetCore.Components.Server;
using MudBlazor.Services;
using NetCore.AutoRegisterDi;
@@ -6,7 +7,6 @@ var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services
.AddMudServices()
.AddRazorComponents()
.AddInteractiveServerComponents();
@@ -15,7 +15,20 @@ builder.Services.RegisterAssemblyPublicNonGenericClasses(System.Reflection.Assem
.Where(t => t.Name.EndsWith("Service"))
.AsPublicImplementedInterfaces();
builder.Services.AddSignalR(e => { e.MaximumReceiveMessageSize = 102400000; });
builder.Services.AddSignalR(e =>
{
// Caddyfiles are kilobytes; this is generous headroom for Monaco editor round-trips
e.MaximumReceiveMessageSize = 512 * 1024;
e.StreamBufferCapacity = 5;
});
// Keep as little per-circuit state resident as practical for a single-user admin UI
builder.Services.Configure<CircuitOptions>(o =>
{
o.DisconnectedCircuitRetentionPeriod = TimeSpan.FromMinutes(1);
o.DisconnectedCircuitMaxRetained = 5;
o.MaxBufferedUnacknowledgedRenderBatches = 3;
});
builder.Services.AddMudServices(config =>
{

View File

@@ -524,6 +524,7 @@
"NetCore.AutoRegisterDi": "[2.2.1, )"
}
}
}
},
"net10.0/linux-musl-x64": {}
}
}

View File

@@ -163,6 +163,10 @@ services:
DockerService__CaddyConfigPathInContainer: "/etc/caddy/Caddyfile"
# To have the access to the caddy config file
user: "1000:1000"
# The .NET GC sizes its heap against the cgroup limit, so this both caps the worst
# case and makes the runtime self-tune downward. Raise it if you run many configs.
mem_limit: 256m
memswap_limit: 256m
ports:
- "8080:8080"
volumes:

View File

@@ -19,6 +19,10 @@
CaddyService__ConfigDir: "/config"
DockerService__CaddyContainerName: "caddy"
user: "1000:1000"
# The .NET GC sizes its heap against the cgroup limit, so this both caps the
# worst case and makes the runtime self-tune downward.
mem_limit: 256m
memswap_limit: 256m
ports:
- "8080:8080"
volumes: