GNU/Linux >> Znalost Linux >  >> Panels >> Docker

Kompletní kontejnerizovaná mikroslužba .NET Core Application, která je co nejmenší

Dobře, technicky možná nejde o mikroslužbu, ale to je v dnešní době populární slovo, že? Před několika týdny jsem blogoval o vylepšeních nasazení ASP.NET Core na webu Zeit's now.sh a vytváření obrázků malých kontejnerů. Na konci jsem byl schopen snížit velikost mé nádoby na polovinu.

Ořezávání, které jsem používal, je experimentální a velmi agresivní. Pokud aplikace načítá věci za běhu – jako to někdy dělá ASP.NET Razor Pages – může se stát, že se za běhu objeví podivné chyby, když chybí typ. Některé typy mohly být oříznuty!

Například:

fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HLGQ1DIEF1KV", Request id "0HLGQ1DIEF1KV:00000001": An unhandled exception was thrown by the application.
System.TypeLoadException: Could not load type 'Microsoft.AspNetCore.Diagnostics.IExceptionHandlerPathFeature' from assembly 'Microsoft.Extensions.Primitives, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'.
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Hosting.Internal.HostingApplication.ProcessRequestAsync(Context context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

Jejda!

Dělám samostatné nasazení a pak oříznu výsledek! Richard Lander má skvělý příklad dockerfile. Všimněte si, jak dělá přidávání balíčku pomocí dotnet CLI s "dotnet add package" a následným oříznutím v rámci soubor Dockerfile (na rozdíl od toho, abyste jej přidali do csproj místní vývojové kopie).

Přidávám Tree Trimming Linker do Dockerfile, takže k oříznutí dojde, když je vytvořen obrázek kontejneru. Používám příkaz dotnet k "dotnet přidat balíček ILLlink.Tasks. To znamená, že nemusím odkazovat na balíček linkeru v době vývoje - vše je v době sestavení kontejneru."

FROM microsoft/dotnet:2.1-sdk-alpine AS build
WORKDIR /app

# copy csproj and restore as distinct layers
COPY *.sln .
COPY nuget.config .
COPY superzeit/*.csproj ./superzeit/
RUN dotnet restore

# copy everything else and build app
COPY . .
WORKDIR /app/superzeit
RUN dotnet build

FROM build AS publish
WORKDIR /app/superzeit
# add IL Linker package
RUN dotnet add package ILLink.Tasks -v 0.1.5-preview-1841731 -s https://dotnet.myget.org/F/dotnet-core/api/v3/index.json
RUN dotnet publish -c Release -o out -r linux-musl-x64 /p:ShowLinkerSizeComparison=true

FROM microsoft/dotnet:2.1-runtime-deps-alpine AS runtime
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
WORKDIR /app
COPY --from=publish /app/superzeit/out ./
ENTRYPOINT ["./superzeit"]

Nakonec jsem narazil na tuto chybu v Linkeru (není uvolněn), ale existuje snadné řešení. Potřebuji pouze nastavit vlastnost CrossGenDuringPublish do false v souboru projektu.

Pokud se podíváte na pokročilé pokyny pro linker, můžete vidět, že můžete „rootovat“ typy nebo sestavy. Root znamená "nezahrávejte si s tím nebo s věcmi, které na nich visí." Potřebuji tedy svou aplikaci cvičit za běhu a ujistit se, že jsou k dispozici všechny typy, které moje aplikace potřebuje, ale žádné zbytečné.

Přidal jsem sestavy, které jsem si chtěl ponechat (ne odstranit) při ořezávání/propojování s mým projektovým souborem:

<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<CrossGenDuringPublish>false</CrossGenDuringPublish>
</PropertyGroup>

<ItemGroup>
<LinkerRootAssemblies Include="Microsoft.AspNetCore.Mvc.Razor.Extensions;Microsoft.Extensions.FileProviders.Composite;Microsoft.Extensions.Primitives;Microsoft.AspNetCore.Diagnostics.Abstractions" />
</ItemGroup>

<ItemGroup>
<!-- this can be here, or can be done all at runtime in the Dockerfile -->
<!-- <PackageReference Include="ILLink.Tasks" Version="0.1.5-preview-1841731" /> -->
<PackageReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

</Project>

Moje strategie, jak zjistit, které sestavy „zakořenit“ a vyloučit z ořezávání, bylo doslova jen opakovat. Sestavte, upravte, otestujte, přidejte sestavu přečtením chybové zprávy a opakujte.

Tato ukázková aplikace ASP.NET Core bude nasazena čistě na Zeit s co nejmenší obrazovou stopou. https://github.com/shanselman/superzeit

Dále zkusím skutečnou mikroslužbu (na rozdíl od kompletní webové stránky, což je to, co to je) a uvidím, jak malý to mohu získat. Taková zábava!

AKTUALIZACE: Tato technika funguje také s "dotnet new webapi" a je asi 73 megů na "docker images" a je to 34 megů, když jsou odeslány a stlačeny přes "nyní" CLI Zeit.

Sponzor: Rider 2018.2 je tady! Publikování na IIS, podpora Docker v ladicím programu, vestavěná kontrola pravopisu, podpora MacBook Touch Bar, plná podpora C# 7.3, pokročilá podpora Unity a další.


Docker
  1. Jak nainstalovat .NET Core na Debian 10

  2. Jaké jsou vlastnosti aplikace, která se stane základní/předinstalovanou/výchozí aplikací Ubuntu?

  3. .NET core X509Store na linuxu

  1. Je možné provést kompletní zálohu VPS v samotném VPS?

  2. Kompletní kontejnerizovaná mikroslužba .NET Core Application, která je co nejmenší

  3. Zjištění, že aplikace .NET Core běží v kontejneru Docker a SkippableFacts v XUnit

  1. Optimalizace velikostí obrazu ASP.NET Core Docker

  2. Podporuje .NET Core v Linuxu Visual Basic?

  3. Spuštění samostatné aplikace ASP.NET Core na Ubuntu