Dela via


Containerisera en .NET-appreferens

I den här referensartikeln får du lära dig hur du konfigurerar containeravbildningen som genereras när du publicerar en .NET-app som en container. Den här artikeln beskriver de olika egenskaper som du kan ange för att styra avbildningen, körningsmiljön och kommandona som körs när containern startar.

Konfigurera containeravbildning

Du kan styra många aspekter av den genererade containern via MSBuild-egenskaper. Om du kan använda ett kommando i en Dockerfile för att ange en konfiguration kan du göra samma sak via MSBuild.

Not

De enda undantagen är RUN kommandon. På grund av hur containrar skapas kan de inte emuleras. Om du behöver den här funktionen kan du överväga att använda en Dockerfile- för att skapa dina containeravbildningar.

Det går inte att utföra RUN kommandon med .NET SDK. Dessa kommandon används ofta för att installera vissa OS-paket eller skapa en ny os-användare, eller valfritt antal godtyckliga saker. Om du vill fortsätta använda .NET SDK-containerbyggfunktionen kan du i stället skapa en anpassad basavbildning med dessa ändringar och sedan använda den här basavbildningen. Mer information finns i ContainerBaseImage.

ContainerArchiveOutputPath

Om du vill skapa en containeravbildning i ett tar.gz arkiv använder du egenskapen ContainerArchiveOutputPath. Den här funktionen är användbar om arbetsflödet inte är enkelt och kräver att du till exempel kör ett genomsökningsverktyg över dina bilder innan du push-överför dem. När arkivet har skapats kan du flytta det, skanna det eller läsa in det i en lokal Docker-verktygskedja.

Om du vill publicera i ett arkiv lägger du till egenskapen ContainerArchiveOutputPath i kommandot dotnet publish, till exempel:

dotnet publish \
  -p PublishProfile=DefaultContainer \
  -p ContainerArchiveOutputPath=./images/sdk-container-demo.tar.gz

Du kan ange antingen ett mappnamn eller en sökväg med ett specifikt filnamn. Om du anger mappnamnet heter filnamnet som genererats för avbildningsarkivfilen $(ContainerRepository).tar.gz. Dessa arkiv kan innehålla flera taggar inuti dem, bara när en enda fil skapas för alla ContainerImageTags.

Namngivningskonfiguration för containeravbildningar

Containeravbildningar följer en specifik namngivningskonvention. Avbildningens namn består av flera delar, registret, valfri port, lagringsplats och valfri tagg och familj.

REGISTRY[:PORT]/REPOSITORY[:TAG[-FAMILY]]

Tänk dig till exempel det fullständigt kvalificerade mcr.microsoft.com/dotnet/runtime:8.0-alpine avbildningsnamnet:

  • mcr.microsoft.com är registret (och representerar i det här fallet Microsoft-containerregistret).
  • dotnet/runtime är lagringsplatsen (men vissa anser att detta är user/repository).
  • 8.0-alpine är taggen och familjen (familjen är en valfri specificerare som hjälper till att skilja os-paketering).

Vissa egenskaper som beskrivs i följande avsnitt motsvarar hantering av delar av det genererade avbildningsnamnet. Tänk på följande tabell som mappar relationen mellan avbildningsnamnet och byggegenskaperna:

Del av bildnamn MSBuild-egenskap Exempelvärden
REGISTRY[:PORT] ContainerRegistry mcr.microsoft.com:443
PORT ContainerPort :443
REPOSITORY ContainerRepository dotnet/runtime
TAG ContainerImageTag 8.0
FAMILY ContainerFamily -alpine

I följande avsnitt beskrivs de olika egenskaper som kan användas för att styra den genererade containeravbildningen.

ContainerBaseImage

Egenskapen för containerbasavbildningen styr avbildningen som används som grund för avbildningen. Som standard härleds följande värden baserat på egenskaperna för projektet:

  • Om projektet är fristående används mcr.microsoft.com/dotnet/runtime-deps-avbildningen som basavbildning.
  • Om projektet är ett ASP.NET Core-projekt används den mcr.microsoft.com/dotnet/aspnet bilden som basavbildning.
  • Annars används den mcr.microsoft.com/dotnet/runtime bilden som basavbildning.

Taggen för avbildningen härleds till den numeriska komponenten i den valda TargetFramework. Ett projekt som är inriktat på net6.0 resulterar till exempel i taggen 6.0 för den härledda basavbildningen, och ett net7.0-linux-projekt använder taggen 7.0 och så vidare.

Om du anger ett värde här bör du ange det fullständigt kvalificerade namnet på bilden som ska användas som bas, inklusive eventuella taggar som du föredrar:

<PropertyGroup>
    <ContainerBaseImage>mcr.microsoft.com/dotnet/runtime:8.0</ContainerBaseImage>
</PropertyGroup>

Med .NET SDK version 8.0.200 förbättras ContainerBaseImage slutsatsdragning för att optimera storlek och säkerhet:

  • Om du riktar in dig på linux-musl-x64- eller linux-musl-arm64 Runtime-identifierare väljer du automatiskt de alpine bildvarianterna för att säkerställa att projektet körs:
    • Om projektet använder PublishAot=truenightly/runtime-depsjammy-chiseled-aot variant av basavbildningen för bästa storlek och säkerhet.
    • Om projektet använder InvariantGlobalization=false används de -extra varianterna för att säkerställa att lokaliseringen fortfarande fungerar.

Mer information om storlekar och egenskaper för bildvarianter finns i .NET 8.0 Container Image Size Report.

ContainerFamily

Från och med .NET 8 kan du använda egenskapen ContainerFamily MSBuild för att välja en annan familj med Microsoft-tillhandahållna containeravbildningar som basavbildning för din app. När det här värdet anges läggs det till i slutet av den valda TFM-specifika taggen, vilket ändrar taggen som anges. Om du till exempel vill använda Alpine Linux-varianterna av .NET-basavbildningarna kan du ange ContainerFamily till alpine:

<PropertyGroup>
    <ContainerFamily>alpine</ContainerFamily>
</PropertyGroup>

Den föregående projektkonfigurationen resulterar i en slutlig tagg med 8.0-alpine för en .NET 8-målapp.

Det här fältet är fritt format och kan ofta användas för att välja olika operativsystemdistributioner, standardpaketkonfigurationer eller andra smak ändringar i en basavbildning. Det här fältet ignoreras när ContainerBaseImage anges. Mer information finns i .NET-containeravbildningar.

ContainerRuntimeIdentifier(s)

Egenskapen ContainerRuntimeIdentifier anger operativsystemet och arkitekturen för containern om ContainerBaseImage stöder flera plattformar. Till exempel stöder mcr.microsoft.com/dotnet/runtime-avbildningen linux-x64, linux-arm, linux-arm64och win10-x64. Som standard är detta inställt på den RuntimeIdentifier som används vid publicering av containern. Vanligtvis behöver du inte ange den här egenskapen explicit. Använd i stället alternativet -r med kommandot dotnet publish. Om den valda avbildningen inte stöder den angivna RuntimeIdentifieranger ett fel de identifierare som stöds.

Du kan alltid ange egenskapen ContainerBaseImage till ett fullständigt kvalificerat avbildningsnamn, inklusive taggen, för att undvika att behöva använda den här egenskapen alls.

<PropertyGroup>
    <ContainerRuntimeIdentifier>linux-arm64</ContainerRuntimeIdentifier>
</PropertyGroup>

Om du vill ange flera containerkörningsidentifierare för avbildningar med flera arkitekturer använder du en semikolonavgränsad uppsättning körningsidentifierare i egenskapen ContainerRuntimeIdentifiers, ungefär som att ange flera TargetFrameworks:

<PropertyGroup>
    <ContainerRuntimeIdentifiers>linux-x64;linux-arm64</ContainerRuntimeIdentifiers>
</PropertyGroup>

Mer information om körningsidentifierare som stöds av .NET finns i RID-katalog.

ContainerRegistry

Egenskapen containerregister styr målregistret, den plats som den nyligen skapade avbildningen kommer att push-överföras till. Som standard skickas den till den lokala Docker-daemonen, men du kan också ange ett fjärrregister. När du använder ett fjärrregister som kräver autentisering autentiserar du med hjälp av de välkända docker login mekanismerna. Mer information finns i autentisera till containerregister för mer information. Ett konkret exempel på hur du använder den här egenskapen finns i följande XML-exempel:

<PropertyGroup>
    <ContainerRegistry>registry.mycorp.com:1234</ContainerRegistry>
</PropertyGroup>

Den här verktygsverktyget stöder publicering till alla register som har stöd för Docker Registry HTTP API V2. Detta inkluderar följande register explicit (och sannolikt många mer implicit):

Information om hur du arbetar med dessa register finns i registerspecifika anteckningar.

ContainerRepository

Containerlagringsplatsen är namnet på själva avbildningen, till exempel dotnet/runtime eller my-app. Som standard används projektets AssemblyName.

<PropertyGroup>
    <ContainerRepository>my-app</ContainerRepository>
</PropertyGroup>

Bildnamn består av ett eller flera snedstrecksavgränsade segment, som var och en bara kan innehålla alfanumeriska gemener, punkter, understreck och bindestreck, och måste börja med en bokstav eller siffra. Andra tecken resulterar i ett fel som utlöses.

ContainerImageTag(s)

Egenskapen containeravbildningstagg styr taggarna som genereras för avbildningen. Om du vill ange en enskild tagg använder du ContainerImageTag och för flera taggar använder du ContainerImageTags.

Viktig

När du använder ContainerImageTagsfår du flera bilder, en per unik tagg.

Taggar används ofta för att referera till olika versioner av en app, men de kan också referera till olika operativsystemdistributioner eller till och med olika konfigurationer.

Från och med .NET 8, när en tagg inte anges är standardvärdet latest.

Om du vill åsidosätta standardvärdet anger du något av följande:

<PropertyGroup>
    <ContainerImageTag>1.2.3-alpha2</ContainerImageTag>
</PropertyGroup>

Om du vill ange flera taggar använder du en semikolonavgränsad uppsättning taggar i egenskapen ContainerImageTags, ungefär som att ange flera TargetFrameworks:

<PropertyGroup>
    <ContainerImageTags>1.2.3-alpha2;latest</ContainerImageTags>
</PropertyGroup>

Taggar kan bara innehålla upp till 127 alfanumeriska tecken, punkter, understreck och bindestreck. De måste börja med ett alfanumeriskt tecken eller ett understreck. Alla andra formulär resulterar i ett fel som utlöses.

Not

När du använder ContainerImageTags eller någon MSBuild-egenskap som behöver konfigurera ; avgränsade värden. Om du anropar dotnet publish från kommandoraden (vilket är fallet med de flesta CI/CD-miljöer) måste du förstå begränsningarna i miljöns oförmåga att skilja avgränsare och citattecken åt, vilket kräver en korrekt flykt. Detta skiljer sig mellan PowerShell och Bash. Överväg följande dotnet publish kommandon i respektive miljö:

dotnet publish --os linux --arch x64 /t:PublishContainer /p:ContainerImageTags=`"1.2.3-alpha2`;latest`"

I PowerShell måste både ; och " tecken vara undantagna.

dotnet publish --os linux --arch x64 /t:PublishContainer /p:ContainerImageTags=\"1.2.3-alpha2;latest\"

I Bash behöver bara det " tecknet vara undantaget.

Detta resulterar i att två bilder genereras: my-app:1.2.3-alpha2 och my-app:latest.

Dricks

Om du har problem med egenskapen ContainerImageTags kan du överväga att omfångssöka en miljövariabel ContainerImageTags i stället:

$Env:ContainerImageTags='1.2.3;latest'; dotnet publish --os linux --arch x64 /t:PublishContainer

ContainerLabel

Containeretiketten lägger till en metadataetikett i containern. Etiketter används ofta för att lagra versions- och redigeringsmetadata för användning av säkerhetsskannrar och andra infrastrukturverktyg. Du kan ange valfritt antal containeretiketter.

Noden ContainerLabel har två attribut:

  • Include: Etikettens nyckel.
  • Value: Etikettens värde (detta kan vara tomt).
<ItemGroup>
    <ContainerLabel Include="org.contoso.businessunit" Value="contoso-university" />
</ItemGroup>

En lista över etiketter som skapas som standard finns i standardcontaineretiketter.

Konfigurera containerkörning

Om du vill styra körningen av containern kan du använda följande MSBuild-egenskaper.

ContainerWorkingDirectory

Containerns arbetskatalognod styr arbetskatalogen för containern, katalogen som kommandon körs i om inte annat kommando körs.

Som standard används /app katalogvärdet som arbetskatalog.

<PropertyGroup>
    <ContainerWorkingDirectory>/bin</ContainerWorkingDirectory>
</PropertyGroup>

ContainerPort

Containerporten lägger till TCP-portar (Transmission Control Protocol) eller UDP-portar (User Datagram Protocol) i listan över kända portar för containern. Detta gör det möjligt för containerkörningar som Docker att mappa dessa portar till värddatorn automatiskt. Detta används ofta som dokumentation för containern, men kan också användas för att aktivera automatisk portmappning.

Noden ContainerPort har två attribut:

  • Include: Portnumret som ska exponeras.
  • Type: Standardvärden för tcp, giltiga värden är antingen tcp eller udp.
<ItemGroup>
    <ContainerPort Include="80" Type="tcp" />
</ItemGroup>

Från och med .NET 8 härleds ContainerPort när den inte uttryckligen tillhandahålls baserat på flera välkända ASP.NET miljövariabler:

  • ASPNETCORE_URLS
  • ASPNETCORE_HTTP_PORTS
  • ASPNETCORE_HTTPS_PORTS

Om dessa miljövariabler finns parsas deras värden och konverteras till TCP-portmappningar. Dessa miljövariabler läss från basavbildningen, om de finns eller från de miljövariabler som definierats i projektet via ContainerEnvironmentVariable objekt. Mer information finns i ContainerEnvironmentVariable.

ContainerEnvironmentVariable

Med variabelnoden för containermiljön kan du lägga till miljövariabler i containern. Miljövariabler är tillgängliga för appen som körs i containern omedelbart och används ofta för att ändra körningsbeteendet för appen som körs.

Noden ContainerEnvironmentVariable har två attribut:

  • Include: Namnet på miljövariabeln.
  • Value: Värdet för miljövariabeln.
<ItemGroup>
  <ContainerEnvironmentVariable Include="LOGGER_VERBOSITY" Value="Trace" />
</ItemGroup>

Mer information finns i .NET-miljövariabler.

Not

Det går för närvarande inte att ange miljövariabler från .NET CLI när du publicerar en containeravbildning. Mer information finns i GitHub: .NET SDK container builds.

Konfigurera containerkommandon

Som standard startar containerverktygen din app med antingen den genererade AppHost-binärfilen för din app (om appen använder en AppHost) eller kommandot dotnet plus appens DLL.

Du kan dock styra hur appen körs med hjälp av en kombination av ContainerAppCommand, ContainerAppCommandArgs, ContainerDefaultArgsoch ContainerAppCommandInstruction.

Dessa olika konfigurationspunkter finns eftersom olika basavbildningar använder olika kombinationer av containern ENTRYPOINT och COMMAND egenskaper, och du vill kunna stödja dem alla. Standardvärdena bör vara användbara för de flesta appar, men om du vill anpassa appstartbeteendet bör du:

  • Identifiera binärfilen som ska köras och ange den som ContainerAppCommand
  • Identifiera vilka argument som krävs för att programmet ska kunna köras och ange dem som ContainerAppCommandArgs
  • Identifiera vilka argument (om sådana finns) som är valfria och kan åsidosättas av en användare och ange dem som ContainerDefaultArgs
  • Ange ContainerAppCommandInstruction till DefaultArgs

Mer information finns i följande konfigurationsobjekt.

ContainerAppCommand

Konfigurationsobjektet för appkommandot är appens logiska startpunkt. För de flesta appar är detta AppHost, den genererade körbara binärfilen för din app. Om din app inte genererar en AppHost är det här kommandot vanligtvis dotnet <your project dll>. Dessa värden tillämpas efter någon ENTRYPOINT i bascontainern, eller direkt om ingen ENTRYPOINT har definierats.

Konfigurationen ContainerAppCommand har en enda egenskap Include som representerar kommandot, alternativet eller argumentet som ska användas i kommandot entrypoint:

<ItemGroup Label="ContainerAppCommand Assignment">
  <!-- This is how you would start the dotnet ef tool in your container -->
  <ContainerAppCommand Include="dotnet" />
  <ContainerAppCommand Include="ef" />

  <!-- This shorthand syntax means the same thing, note the semicolon separating the tokens. -->
  <ContainerAppCommand Include="dotnet;ef" />
</ItemGroup>

ContainerAppCommandArgs

Det här appkommandot args-konfigurationsobjektet representerar alla logiskt obligatoriska argument för din app som ska tillämpas på ContainerAppCommand. Som standard genereras ingen för en app. När det är dags tillämpas args på containern när den körs.

Konfigurationen ContainerAppCommandArgs har en enda egenskap för Include som representerar det alternativ eller argument som ska tillämpas på kommandot ContainerAppCommand.

<ItemGroup>
  <!-- Assuming the ContainerAppCommand defined above,
       this would be the way to force the database to update.
  -->
  <ContainerAppCommandArgs Include="database" />
  <ContainerAppCommandArgs Include="update" />

  <!-- This is the shorthand syntax for the same idea -->
  <ContainerAppCommandArgs Include="database;update" />
</ItemGroup>

ContainerDefaultArgs

Det här standardinställningsobjektet args representerar alla användaröversidosättbara argument för din app. Det här är ett bra sätt att tillhandahålla standardvärden som din app kan behöva köra på ett sätt som gör det enkelt att starta, men ändå enkelt att anpassa.

Konfigurationen ContainerDefaultArgs har en enda egenskap för Include som representerar det alternativ eller argument som ska tillämpas på kommandot ContainerAppCommand.

<ItemGroup>
  <!-- Assuming the ContainerAppCommand defined above,
       this would be the way to force the database to update.
  -->
  <ContainerDefaultArgs Include="database" />
  <ContainerDefaultArgs Include="update" />

  <!-- This is the shorthand syntax for the same idea -->
  <ContainerDefaultArgs Include="database;update" />
</ItemGroup>

ContainerAppCommandInstruction

Konfigurationen av appkommandoinstruktioner hjälper dig att styra hur ContainerEntrypoint, ContainerEntrypointArgs, ContainerAppCommand, ContainerAppCommandArgsoch ContainerDefaultArgs kombineras för att bilda det slutliga kommandot som körs i containern. Detta beror mycket på om en ENTRYPOINT finns i basavbildningen. Den här egenskapen har ett av tre värden: "DefaultArgs", "Entrypoint"eller "None".

  • Entrypoint:
    • I det här läget definieras startpunkten av ContainerAppCommand, ContainerAppCommandArgsoch ContainerDefaultArgs.
  • None:
    • I det här läget definieras startpunkten av ContainerEntrypoint, ContainerEntrypointArgsoch ContainerDefaultArgs.
  • DefaultArgs:
    • Det här är det mest komplexa läget – om inget av de ContainerEntrypoint[Args] objekten finns används ContainerAppCommand[Args] och ContainerDefaultArgs för att skapa startpunkten och kommandot. Basavbildningens startpunkt för basavbildningar som har hårdkodad för att dotnet eller /usr/bin/dotnet hoppas över så att du har fullständig kontroll.
    • Om både ContainerEntrypoint och ContainerAppCommand finns blir ContainerEntrypoint startpunkten och ContainerAppCommand blir kommandot .

Not

Konfigurationsobjekten ContainerEntrypoint och ContainerEntrypointArgs är inaktuella från och med .NET 8.

Viktig

Detta gäller för avancerade användare– de flesta appar behöver inte anpassa sin startpunkt i den här utsträckningen. Mer information och om du vill ange användningsfall för dina scenarier finns GitHub: .NET SDK-container skapar diskussioner.

ContainerUser

Egenskapen för användarkonfiguration styr standardanvändaren som containern körs som. Detta används ofta för att köra containern som en icke-rotanvändare, vilket är bästa praxis för säkerhet. Det finns några begränsningar för den här konfigurationen att känna till:

  • Den kan ha olika former – användarnamn, linux-användar-ID, gruppnamn, linux-grupp-ID, username:groupnameoch andra ID-varianter.
  • Det finns ingen verifiering av att den angivna användaren eller gruppen finns på bilden.
  • Om du ändrar användaren kan appens beteende ändras, särskilt när det gäller saker som filsystem behörigheter.

Standardvärdet för det här fältet varierar beroende på projektets TFM och måloperativsystemet:

  • Om du riktar in dig på .NET 8 eller senare och använder Microsoft Runtime-avbildningarna:
    • i Linux används den rotlösa användaren app (även om den refereras av dess användar-ID)
    • i Windows används den rotlösa användaren ContainerUser
  • Annars används ingen standard ContainerUser
<PropertyGroup>
  <ContainerUser>my-existing-app-user</ContainerUser>
</PropertyGroup>

Dricks

Miljövariabeln APP_UID används för att ange användarinformation i containern. Det här värdet kan komma från miljövariabler som definierats i basavbildningen (som microsoft .NET-avbildningar gör), eller så kan du ställa in det själv via ContainerEnvironmentVariable syntax.

Om du vill konfigurera appen så att den körs som en rotanvändare anger du egenskapen ContainerUser till root. Lägg till följande i projektfilen:

<PropertyGroup>
  <ContainerUser>root</ContainerUser>
</PropertyGroup>

Du kan också ange det här värdet när du anropar dotnet publish från kommandoraden:

dotnet publish -p ContainerUser=root

Standardcontaineretiketter

Etiketter används ofta för att tillhandahålla konsekventa metadata på containeravbildningar. Det här paketet innehåller några standardetiketter för att uppmuntra till bättre underhåll av de genererade bilderna.

  • org.opencontainers.image.created är inställt på ISO 8601-formatet för det aktuella värdet för DateTime.UtcNow.

Mer information finns i Implementera konventionella etiketter ovanpå befintlig etikettinfrastruktur.

Se även