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 äruser/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
- ellerlinux-musl-arm64
Runtime-identifierare väljer du automatiskt dealpine
bildvarianterna för att säkerställa att projektet körs:- Om projektet använder
PublishAot=true
nightly/runtime-deps
jammy-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.
- Om projektet använder
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-arm64
och 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 RuntimeIdentifier
anger 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):
- Azure Container Registry
- Amazon Elastic Container Registry
- Google Artifact Registry
- Docker Hub
- GitHub-paket
- GitLab-värdbaserad containerregister
- Quay.io
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 ContainerImageTags
få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örtcp
, giltiga värden är antingentcp
ellerudp
.
<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
, ContainerDefaultArgs
och 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
tillDefaultArgs
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
, ContainerAppCommandArgs
och 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
,ContainerAppCommandArgs
ochContainerDefaultArgs
.
- I det här läget definieras startpunkten av
-
None
:- I det här läget definieras startpunkten av
ContainerEntrypoint
,ContainerEntrypointArgs
ochContainerDefaultArgs
.
- I det här läget definieras startpunkten av
-
DefaultArgs
:- Det här är det mest komplexa läget – om inget av de
ContainerEntrypoint[Args]
objekten finns användsContainerAppCommand[Args]
ochContainerDefaultArgs
för att skapa startpunkten och kommandot. Basavbildningens startpunkt för basavbildningar som har hårdkodad för attdotnet
eller/usr/bin/dotnet
hoppas över så att du har fullständig kontroll. - Om både
ContainerEntrypoint
ochContainerAppCommand
finns blirContainerEntrypoint
startpunkten ochContainerAppCommand
blir kommandot .
- Det här är det mest komplexa läget – om inget av de
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:groupname
och 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
- i Linux används den rotlösa användaren
- 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.