Containerizzare un'app .NET con dotnet publish
I contenitori hanno molte funzionalità e vantaggi, ad esempio un'infrastruttura non modificabile, offrono un'architettura portabile e consentono la scalabilità. L'immagine può essere usata per creare contenitori per l'ambiente di sviluppo locale, il cloud privato o il cloud pubblico. In questa esercitazione si apprenderà come inserire in contenitori un'applicazione .NET usando il comando dotnet publish.
Prerequisiti
Installare i prerequisiti seguenti:
- .NET 8+ SDK
Se è installato .NET, usare il comandodotnet --info
per determinare l'SDK in uso. - Docker Community Edition
- .NET 7+ SDK
Se è installato .NET, usare il comandodotnet --info
per determinare l'SDK in uso. - Docker Community Edition
Oltre a questi prerequisiti, è consigliabile acquisire familiarità con i servizi di lavoro in .NET.
Creare un'app .NET
È necessaria un'app .NET da inserire in contenitori, quindi iniziare creando una nuova app da un modello. Aprire il terminale, creare una cartella di lavoro (sample-directory) se non è già stato fatto e modificare le directory in modo trovarcisi dentro. Nella cartella di lavoro eseguire il comando seguente per creare un nuovo progetto in una sottodirectory denominata Ruolo di lavoro:
dotnet new worker -o Worker -n DotNet.ContainerImage
L'albero delle cartelle è simile al seguente:
📁 sample-directory
└──📂 Worker
├──appsettings.Development.json
├──appsettings.json
├──DotNet.ContainerImage.csproj
├──Program.cs
├──Worker.cs
└──📂 obj
├── DotNet.ContainerImage.csproj.nuget.dgspec.json
├── DotNet.ContainerImage.csproj.nuget.g.props
├── DotNet.ContainerImage.csproj.nuget.g.targets
├── project.assets.json
└── project.nuget.cache
Il comando dotnet new
crea una nuova cartella denominata Ruolo di lavoro e genera un servizio di lavoro che, quando viene eseguito, registra un messaggio ogni secondo. Nella sessione del terminale, modificare le directory e passare alla cartella ruolo di lavoro. Usare il comando dotnet run
per avviare l'app.
dotnet run
Building...
info: DotNet.ContainerImage.Worker[0]
Worker running at: 10/18/2022 08:56:00 -05:00
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: .\Worker
info: DotNet.ContainerImage.Worker[0]
Worker running at: 10/18/2022 08:56:01 -05:00
info: DotNet.ContainerImage.Worker[0]
Worker running at: 10/18/2022 08:56:02 -05:00
info: DotNet.ContainerImage.Worker[0]
Worker running at: 10/18/2022 08:56:03 -05:00
info: Microsoft.Hosting.Lifetime[0]
Application is shutting down...
Attempting to cancel the build...
Il modello di lavoro esegue cicli illimitati. Usare il comando di annullamento CTRL+C per arrestarla.
Aggiungere pacchetto NuGet
Il pacchetto NuGet Microsoft.NET.Build.Containers è attualmente necessario per pubblicare progetti non Web come contenitore. Per aggiungere il pacchetto NuGet Microsoft.NET.Build.Containers
al modello del ruolo di lavoro, eseguire il comando dotnet add packageseguente:
dotnet add package Microsoft.NET.Build.Containers
Suggerimento
Se si sta creando un'app Web e si usa .NET SDK 7.0.300 o versione successiva, il pacchetto non è necessario. L'SDK contiene le stesse funzionalità predefinite.
Impostare il nome dell'immagine del contenitore
Durante la pubblicazione di un'app come contenitore sono disponibili diverse opzioni di configurazione.
Per impostazione predefinita, il nome dell'immagine del contenitore è il AssemblyName
del progetto. Se tale nome non è valido come nome dell'immagine del contenitore, è possibile eseguirne l'override specificando un ContainerRepository
come illustrato nel file di progetto seguente:
<Project Sdk="Microsoft.NET.Sdk.Worker">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>dotnet-DotNet.ContainerImage-2e40c179-a00b-4cc9-9785-54266210b7eb</UserSecretsId>
<ContainerRepository>dotnet-worker-image</ContainerRepository>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
</ItemGroup>
</Project>
Per altre informazioni, vedere ContainerRepository.
Per impostazione predefinita, il nome dell'immagine del contenitore è il AssemblyName
del progetto. Se tale nome non è valido come nome dell'immagine del contenitore, è possibile eseguirne l'override specificando un oggetto (ContainerImageName
obsoleto) o ContainerRepository
preferito, come illustrato nel file di progetto seguente:
<Project Sdk="Microsoft.NET.Sdk.Worker">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>dotnet-DotNet.ContainerImage-2e40c179-a00b-4cc9-9785-54266210b7eb</UserSecretsId>
<ContainerImageName>dotnet-worker-image</ContainerImageName>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
<PackageReference Include="Microsoft.NET.Build.Containers" Version="7.0.401" />
</ItemGroup>
</Project>
Per altre informazioni, vedere ContainerImageName.
Pubblicare un'app .NET
Per pubblicare l'app .NET come contenitore, usare il comando dotnet publish seguente:
dotnet publish --os linux --arch x64 /t:PublishContainer -c Release
Il comando precedente dell'interfaccia della riga di comando di .NET pubblica l'app come contenitore:
- Destinare Linux come sistema operativo (
--os linux
). - Specifica di un'architettura x64 (
--arch x64
). - Uso della configurazione della versione (
-c Release
).
Importante
Per compilare il contenitore in locale, è necessario che il daemon Docker sia in esecuzione. Se non è in esecuzione quando si tenta di pubblicare l'app come contenitore, si verifica un errore simile al seguente:
..\build\Microsoft.NET.Build.Containers.targets(66,9): error MSB4018:
The "CreateNewImage" task failed unexpectedly. [..\Worker\DotNet.ContainerImage.csproj]
Suggerimento
A seconda del tipo di app che si stanno mettendo in contenitori, le opzioni della riga di comando (opzioni) possono variare. Ad esempio, l'argomento /t:PublishContainer
è necessario solo per le app .NET non Web, ad esempio i modelli di console
e worker
. Per i modelli Web, sostituire l'argomento /t:PublishContainer
con -p:PublishProfile=DefaultContainer
. Per altre informazioni, vedere Compilazioni di contenitori .NET SDK, problema #141.
Il comando genera un output simile all'output di esempio:
Determining projects to restore...
All projects are up-to-date for restore.
DotNet.ContainerImage -> .\Worker\bin\Release\net8.0\linux-x64\DotNet.ContainerImage.dll
DotNet.ContainerImage -> .\Worker\bin\Release\net8.0\linux-x64\publish\
Building image 'dotnet-worker-image' with tags latest on top of base image mcr.microsoft.com/dotnet/aspnet:8.0
Pushed container 'dotnet-worker-image:latest' to Docker daemon
Determining projects to restore...
All projects are up-to-date for restore.
DotNet.ContainerImage -> .\Worker\bin\Release\net7.0\linux-x64\DotNet.ContainerImage.dll
DotNet.ContainerImage -> .\Worker\bin\Release\net7.0\linux-x64\publish\
Building image 'dotnet-worker-image' with tags 1.0.0 on top of base image mcr.microsoft.com/dotnet/aspnet:7.0
Pushed container 'dotnet-worker-image:1.0.0' to Docker daemon
Questo comando compila l'app del ruolo di lavoro nella cartella publish ed esegue il push del contenitore nel registro Docker locale.
Configurare l'immagine del contenitore
È possibile controllare molti aspetti del contenitore generato tramite le proprietà di MSBuild. In generale, se è possibile usare un comando in un Dockerfile per impostare una configurazione, è possibile eseguire la stessa operazione tramite MSBuild.
Nota
Le uniche eccezioni a questo sono i comandi RUN
. A causa del modo in cui vengono compilati i contenitori, questi non possono essere emulati. Se si ha bisogno di questa funzionalità, è necessario usare un Dockerfile per compilare le immagini del contenitore.
ContainerArchiveOutputPath
A partire da .NET 8, è possibile creare un contenitore direttamente come archivio tar.gz. Questa funzionalità è utile se il flusso di lavoro non è semplice e richiede, ad esempio, di eseguire uno strumento di analisi sulle immagini prima di eseguirne il push. Dopo aver creato l'archivio, è possibile spostarlo, analizzarlo o caricarlo in una toolchain Docker locale.
Per eseguire la pubblicazione in un archivio, aggiungere la proprietà ContainerArchiveOutputPath
al comando dotnet publish
, ad esempio:
dotnet publish \
-p PublishProfile=DefaultContainer \
-p ContainerArchiveOutputPath=./images/sdk-container-demo.tar.gz
È possibile specificare un nome di cartella o un percorso con un nome di file specifico. Se si specifica il nome della cartella, il nome file generato per il file di archivio immagini sarà $(ContainerRepository).tar.gz
. Questi archivi possono contenere più tag al loro interno, solo quando viene creato un singolo file per tutti i ContainerImageTags
.
Configurazione dei nomi delle immagini del contenitore
Le immagini del contenitore seguono una convenzione di denominazione specifica. Il nome dell'immagine è costituito da diverse parti, dal Registro di sistema, dalla porta facoltativa, dal repository e da tag e famiglia facoltativi.
REGISTRY[:PORT]/REPOSITORY[:TAG[-FAMILY]]
Si consideri ad esempio il nome qualificato dell'immagine mcr.microsoft.com/dotnet/runtime:8.0-alpine
:
mcr.microsoft.com
è il registro (e in questo caso rappresenta il registro contenitori Microsoft).dotnet/runtime
è il repository (ma alcuni lo consideranouser/repository
).8.0-alpine
è il tag e la famiglia (la famiglia è un identificatore facoltativo che aiuta a disambiguare la creazione di pacchetti del sistema operativo).
Alcune proprietà descritte nelle sezioni seguenti corrispondono alla gestione delle parti del nome dell'immagine generata. Si consideri la tabella seguente che esegue il mapping della relazione tra il nome dell'immagine e le proprietà di compilazione:
Parte nome immagine | Proprietà MSBuild | Valori di esempio |
---|---|---|
REGISTRY[:PORT] |
ContainerRegistry |
mcr.microsoft.com:443 |
PORT |
ContainerPort |
:443 |
REPOSITORY |
ContainerRepository |
dotnet/runtime |
TAG |
ContainerImageTag |
8.0 |
FAMILY |
ContainerFamily |
-alpine |
Parte nome immagine | Proprietà MSBuild | Valori di esempio |
---|---|---|
REGISTRY[:PORT] |
ContainerRegistry |
mcr.microsoft.com:443 |
PORT |
ContainerPort |
:443 |
REPOSITORY |
ContainerImageName |
dotnet/runtime |
TAG |
ContainerImageTag |
8.0 |
Le sezioni seguenti descrivono le varie proprietà che possono essere usate per controllare l'immagine del contenitore generata.
ContainerBaseImage
La proprietà dell'immagine di base del contenitore controlla l'immagine usata come base per l'immagine. Per impostazione predefinita, i valori seguenti vengono dedotti in base alle proprietà del progetto:
- Se il progetto è autonomo, l'immagine
mcr.microsoft.com/dotnet/runtime-deps
viene usata come immagine di base. - Se il progetto è un progetto ASP.NET Core, l'immagine
mcr.microsoft.com/dotnet/aspnet
viene usata come immagine di base. - In caso contrario, l'immagine
mcr.microsoft.com/dotnet/runtime
viene usata come immagine di base.
Il tag dell'immagine viene dedotto come componente numerico dell'oggetto scelto TargetFramework
. Ad esempio, un progetto destinato a net6.0
restituisce il tag 6.0
dell'immagine di base dedotta e un progetto di net7.0-linux
usa il tag 7.0
e così via.
Se si imposta un valore qui, è necessario impostare il nome completo dell'immagine da usare come base, incluso qualsiasi tag si preferisca:
<PropertyGroup>
<ContainerBaseImage>mcr.microsoft.com/dotnet/runtime:8.0</ContainerBaseImage>
</PropertyGroup>
<PropertyGroup>
<ContainerBaseImage>mcr.microsoft.com/dotnet/runtime:7.0</ContainerBaseImage>
</PropertyGroup>
ContainerFamily
A partire da .NET 8, è possibile usare la proprietà MSBuild ContainerFamily
per scegliere una famiglia diversa di immagini del contenitore fornite da Microsoft come immagine di base per l'app. Se impostato, questo valore viene aggiunto alla fine del tag specifico di TFM selezionato, modificando il tag specificato. Ad esempio, per usare le varianti Alpine Linux delle immagini di base .NET, è possibile impostare ContainerFamily
su alpine
:
<PropertyGroup>
<ContainerFamily>alpine</ContainerFamily>
</PropertyGroup>
La configurazione del progetto precedente genera un tag finale di 8.0-alpine
per un'app di destinazione .NET 8.
Questo campo è in formato libero e spesso può essere usato per selezionare diverse distribuzioni del sistema operativo, configurazioni predefinite dei pacchetti o qualsiasi altra versione delle modifiche apportate a un'immagine di base. Questo campo viene ignorato quando ContainerBaseImage
è impostato. Per altre informazioni, vedere immagini del contenitore .NET.
ContainerRuntimeIdentifier
La proprietà dell'identificatore di runtime del contenitore controlla il sistema operativo e l'architettura usati dal contenitore se ContainerBaseImage supporta più di una piattaforma. Ad esempio, l'immagine mcr.microsoft.com/dotnet/runtime
supporta attualmente linux-x64
, linux-arm
, linux-arm64
e win10-x64
immagini tutte dietro lo stesso tag, quindi gli strumenti devono avere un modo per sapere quale di queste versioni si intende usare. Per impostazione predefinita, questo valore viene impostato sul valore dell'oggetto RuntimeIdentifier
scelto durante la pubblicazione del contenitore. Questa proprietà raramente deve essere impostata in modo esplicito. Usare invece l'opzione -r
per il comando dotnet publish
. Se l'immagine scelta non supporta l’elemento RuntimeIdentifier
scelto, genera un errore che descrive il RuntimeIdentifiers supportato dall'immagine.
È sempre possibile impostare la proprietà ContainerBaseImage
su un nome di immagine completo, incluso il tag, per evitare di dover usare questa proprietà.
<PropertyGroup>
<ContainerRuntimeIdentifier>linux-arm64</ContainerRuntimeIdentifier>
</PropertyGroup>
Per altre informazioni sugli identificatori di runtime supportati da .NET, vedere catalogo RID.
ContainerRegistry
La proprietà del registro contenitori controlla il Registro di sistema di destinazione, ovvero la posizione in cui verrà eseguito il push dell'immagine appena creata. Per impostazione predefinita, viene eseguito il push nel daemon Docker locale, ma è anche possibile specificare un registro remoto. Quando si usa un registro remoto che richiede l'autenticazione, si esegue l'autenticazione usando i meccanismi noti docker login
. Per altre informazioni, vedere Autenticazione nei registri contenitori per altri dettagli. Per un esempio concreto di utilizzo di questa proprietà, considerare l'esempio XML seguente:
<PropertyGroup>
<ContainerRegistry>registry.mycorp.com:1234</ContainerRegistry>
</PropertyGroup>
Questo strumento supporta la pubblicazione in qualsiasi registro che supporta l'API HTTP del Registro Docker V2. Sono inclusi i registri seguenti in modo esplicito (e probabilmente molti altri in modo implicito):
- Registro Azure Container
- Registro Contenitori Amazon Elastic
- Registro artefatti di Google
- Hub docker
- Pacchetti GitHub
- Registro Contenitori ospitato in GitLab
- Quay.io
Per le note sull'uso di questi registri, vedere le note specifiche del Registro di sistema.
ContainerRepository
Il repository del contenitore è il nome dell'immagine stessa, ad esempio dotnet/runtime
o my-app
. Per impostazione predefinita, viene utilizzato l'oggetto AssemblyName
del progetto.
<PropertyGroup>
<ContainerRepository>my-app</ContainerRepository>
</PropertyGroup>
ContainerImageName
Il nome dell'immagine del contenitore controlla il nome dell'immagine stessa, ad esempio dotnet/runtime
o my-app
. Per impostazione predefinita, viene utilizzato l'oggetto AssemblyName
del progetto.
<PropertyGroup>
<ContainerImageName>my-app</ContainerImageName>
</PropertyGroup>
Nota
A partire da .NET 8, ContainerImageName
è deprecato a favore di ContainerRepository
.
I nomi delle immagini sono costituiti da uno o più segmenti delimitati da barre, e ognuno di essi può contenere solo caratteri alfanumerici minuscoli, punti, caratteri di sottolineatura e trattini, e deve iniziare con una lettera o un numero. Tutti gli altri caratteri generano un errore.
ContainerImageTag(s)
La proprietà tag dell'immagine del contenitore controlla i tag generati per l'immagine. Per specificare un singolo tag usare ContainerImageTag
e per più tag usare ContainerImageTags
.
Importante
Quando si usa ContainerImageTags
, si otterranno più immagini, una per tag univoco.
I tag vengono spesso usati per fare riferimento a versioni diverse di un'app, ma possono anche fare riferimento a distribuzioni diverse del sistema operativo o anche a configurazioni diverse.
A partire da .NET 8, quando non viene fornito un tag, il valore predefinito è latest
.
Per impostazione predefinita, l'oggetto Version
del progetto viene usato come valore del tag.
Per eseguire l'override del valore predefinito, specificare una delle opzioni seguenti:
<PropertyGroup>
<ContainerImageTag>1.2.3-alpha2</ContainerImageTag>
</PropertyGroup>
Per specificare più tag, usare un set di tag delimitato da punto e virgola nella proprietà ContainerImageTags
, in modo analogo all'impostazione di più TargetFrameworks
:
<PropertyGroup>
<ContainerImageTags>1.2.3-alpha2;latest</ContainerImageTags>
</PropertyGroup>
I tag possono contenere solo fino a 127 caratteri alfanumerici, punti, caratteri di sottolineatura e trattini. Devono iniziare con un carattere alfanumerico o un carattere di sottolineatura. Qualsiasi altro modulo genera un errore.
Nota
Quando si usa ContainerImageTags
, i tag sono delimitati da un carattere ;
. Se si esegue una chiamata dotnet publish
dalla riga di comando (come nel caso della maggior parte degli ambienti CI/CD), è necessario eseguire il wrapping esterno dei valori in un singolo '
e interno con virgolette doppie "
, ad esempio (='"tag-1;tag-2"'
). Si consideri il comando dotnet publish
seguente:
dotnet publish -p ContainerImageTags='"1.2.3-alpha2;latest"'
Ciò comporta la generazione di due immagini: my-app:1.2.3-alpha2
e my-app:latest
.
Suggerimento
Se si verificano problemi con la proprietà ContainerImageTags
, prendere invece in considerazione l'ambito di una variabile di ambiente ContainerImageTags
:
ContainerImageTags='1.2.3;latest' dotnet publish
ContainerLabel
L'etichetta del contenitore aggiunge un'etichetta di metadati al contenitore. Le etichette non hanno alcun impatto sul contenitore in fase di esecuzione, ma vengono spesso usate per archiviare i metadati di versione e creazione per l'uso da parte di scanner di sicurezza e altri strumenti di infrastruttura. È possibile specificare un numero qualsiasi di etichette del contenitore.
Il nodo ContainerLabel
ha due attributi:
Include
: chiave dell'etichetta.Value
: valore dell'etichetta (può essere vuoto).
<ItemGroup>
<ContainerLabel Include="org.contoso.businessunit" Value="contoso-university" />
</ItemGroup>
Per un elenco di etichette create per impostazione predefinita, vedere etichette dei contenitori predefinite.
Configurare l'esecuzione del contenitore
Per controllare l'esecuzione del contenitore, è possibile usare le proprietà MSBuild seguenti.
ContainerWorkingDirectory
Il nodo della directory di lavoro del contenitore controlla la directory di lavoro del contenitore, la directory in cui vengono eseguiti i comandi se non viene eseguito un altro comando.
Per impostazione predefinita, il valore della directory /app
viene usato come directory di lavoro.
<PropertyGroup>
<ContainerWorkingDirectory>/bin</ContainerWorkingDirectory>
</PropertyGroup>
ContainerPort
La porta del contenitore aggiunge porte TCP o UDP all'elenco di porte note per il contenitore. Ciò consente ai runtime di contenitori come Docker di eseguire automaticamente il mapping di queste porte al computer host. Questa operazione viene spesso usata come documentazione per il contenitore, ma può essere usata anche per abilitare il mapping automatico delle porte.
Il nodo ContainerPort
ha due attributi:
Include
: numero di porta da esporre.Type
: il valore predefinito ètcp
, i valori validi sonotcp
oudp
.
<ItemGroup>
<ContainerPort Include="80" Type="tcp" />
</ItemGroup>
A partire da .NET 8, ContainerPort
viene dedotto quando non viene fornito in modo esplicito in base a diverse variabili di ambiente ASP.NET note:
ASPNETCORE_URLS
ASPNETCORE_HTTP_PORTS
ASPNETCORE_HTTPS_PORTS
Se queste variabili di ambiente sono presenti, i relativi valori vengono analizzati e convertiti in mapping delle porte TCP. Queste variabili di ambiente vengono lette dall'immagine di base, se presente, o dalle variabili di ambiente definite nel progetto tramite elementi ContainerEnvironmentVariable
. Per altre informazioni, vedere ContainerEnvironmentVariable.
ContainerEnvironmentVariable
Il nodo della variabile di ambiente del contenitore consente di aggiungere variabili di ambiente al contenitore. Le variabili di ambiente sono accessibili all'app in esecuzione nel contenitore immediatamente e vengono spesso usate per modificare il comportamento di runtime dell'app in esecuzione.
Il nodo ContainerEnvironmentVariable
ha due attributi:
Include
: nome della variabile di ambiente.Value
: valore della variabile di ambiente.
<ItemGroup>
<ContainerEnvironmentVariable Include="LOGGER_VERBOSITY" Value="Trace" />
</ItemGroup>
Per altre informazioni, vedere variabili di ambiente .NET.
Configurare i comandi del contenitore
Per impostazione predefinita, gli strumenti contenitore avviano l'app usando il file binario AppHost generato per l'app (se l'app usa un AppHost) o il comando dotnet
più la DLL dell'app.
Tuttavia, si può controllare come viene eseguita l'app usando una combinazione di ContainerAppCommand
, ContainerAppCommandArgs
, ContainerDefaultArgs
e ContainerAppCommandInstruction
.
Questi diversi punti di configurazione esistono perché diverse immagini di base usano combinazioni diverse di ENTRYPOINT
del contenitore e delle proprietà COMMAND
, e si vuole essere in grado di supportarli tutti. Le impostazioni predefinite devono essere utilizzabili per la maggior parte delle app, ma se si vuole personalizzare il comportamento di avvio dell'app è necessario:
- Identificare il file binario da eseguire e impostarlo come
ContainerAppCommand
- Identificare gli argomenti necessari per l'esecuzione dell'applicazione e impostarli come
ContainerAppCommandArgs
- Identificare quali argomenti (se presenti) sono facoltativi e possono essere sottoposti a override da un utente e impostarli come
ContainerDefaultArgs
- Impostare
ContainerAppCommandInstruction
suDefaultArgs
Per altre informazioni, vedere gli elementi di configurazione seguenti.
ContainerAppCommand
L'elemento di configurazione del comando dell'app è il punto di ingresso logico dell'app. Per la maggior parte delle app, questo è AppHost, il file binario eseguibile generato per l'app. Se l'app non genera un AppHost, questo comando verrà in genere dotnet <your project dll>
. Questi valori vengono applicati dopo qualsiasi ENTRYPOINT
nel contenitore di base o direttamente se non viene definita alcuna ENTRYPOINT
.
La configurazione ContainerAppCommand
dispone di una singola proprietà Include
, che rappresenta il comando, l'opzione o l'argomento da usare nel comando del punto di ingresso:
<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
Questo elemento di configurazione degli argomenti del comando dell'app rappresenta tutti gli argomenti necessari logicamente per l'app che devono essere applicati a ContainerAppCommand
. Per impostazione predefinita, non ne viene generato nessuno per un'app. Quando presenti, gli argomenti vengono applicati al contenitore quando viene eseguito.
La configurazione di ContainerAppCommandArgs
ha una singola proprietà Include
, che rappresenta l'opzione o l'argomento da applicare al comando 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
Questo elemento di configurazione predefinito degli argomenti rappresenta tutti gli argomenti sostituibili dall'utente per l'app. Questo è un buon modo per fornire le impostazioni predefinite che l'app potrebbe dover eseguire in modo da semplificare l'avvio, ma ancora facile da personalizzare.
La configurazione ContainerDefaultArgs
ha una singola proprietà Include
, che rappresenta l'opzione o l'argomento da applicare al comando 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
La configurazione dell'istruzione del comando dell'app consente di controllare il modo in cui ContainerEntrypoint
, ContainerEntrypointArgs
, ContainerAppCommand
, ContainerAppCommandArgs
e ContainerDefaultArgs
vengono combinati per formare il comando finale eseguito nel contenitore. Questo dipende notevolmente dal fatto che un oggetto ENTRYPOINT
sia presente o meno nell'immagine di base. Questa proprietà accetta uno di questi tre valori: "DefaultArgs"
, "Entrypoint"
o "None"
.
Entrypoint
:- In questa modalità, il punto di ingresso è definito da
ContainerAppCommand
,ContainerAppCommandArgs
eContainerDefaultArgs
.
- In questa modalità, il punto di ingresso è definito da
None
:- In questa modalità, il punto di ingresso è definito da
ContainerEntrypoint
,ContainerEntrypointArgs
eContainerDefaultArgs
.
- In questa modalità, il punto di ingresso è definito da
DefaultArgs
:- Questa è la modalità più complessa: se nessuno degli elementi
ContainerEntrypoint[Args]
è presente,ContainerAppCommand[Args]
eContainerDefaultArgs
vengono usati per creare il punto di ingresso e il comando. Il punto di ingresso dell'immagine di base per le immagini di base che hanno un codice fisso adotnet
o a/usr/bin/dotnet
viene ignorato in modo da avere il controllo completo. - Se sono presenti sia
ContainerEntrypoint
cheContainerAppCommand
,ContainerEntrypoint
diventa il punto di ingresso eContainerAppCommand
diventa il comando.
- Questa è la modalità più complessa: se nessuno degli elementi
Nota
Gli elementi di configurazione ContainerEntrypoint
e ContainerEntrypointArgs
sono stati deprecati a partire da .NET 8.
Importante
Questo è per gli utenti avanzati: la maggior parte delle app non dovrebbe avere bisogno di personalizzare il proprio punto di ingresso fino a questo livello. Per altre informazioni e per fornire casi d'uso per gli scenari, vedere Discussioni sulla compilazione di contenitori di GitHub: .NET SDK.
ContainerUser
La proprietà di configurazione utente controlla l'utente predefinito eseguito dal contenitore. Viene spesso usato per eseguire il contenitore come utente nonroot, che è una procedura consigliata per la sicurezza. Per questa configurazione è necessario tenere presenti alcuni vincoli:
- Può assumere varie forme: nome utente, ID utente linux, nome del gruppo, ID gruppo linux,
username:groupname
e altre varianti ID. - Non può essere verificato che l'utente o il gruppo specificato esista nell'immagine.
- La modifica dell'utente può modificare il comportamento dell'app, soprattutto per quanto riguarda elementi come le autorizzazioni del file system.
Il valore predefinito di questo campo varia in base al progetto TFM e al sistema operativo di destinazione:
- Se si usa come destinazione .NET 8 o versione successiva e si usano le immagini di Runtime Microsoft, procedere in questo modo:
- in Linux viene usato l'utente senza radice
app
(anche se fa riferimento all'ID utente) - in Windows viene usato l'utente senza radice
ContainerUser
- in Linux viene usato l'utente senza radice
- In caso contrario, non viene usato alcun valore predefinito
ContainerUser
<PropertyGroup>
<ContainerUser>my-existing-app-user</ContainerUser>
</PropertyGroup>
Suggerimento
La variabile di ambiente APP_UID
viene usata per impostare le informazioni utente nel contenitore. Questo valore può provenire da variabili di ambiente definite nell'immagine di base (come le immagini Microsoft .NET) oppure è possibile impostarlo manualmente tramite la sintassi ContainerEnvironmentVariable
.
Tuttavia, si può controllare come viene eseguita l'app usando ContainerEntrypoint
e ContainerEntrypointArgs
.
ContainerEntrypoint
Il punto di ingresso del contenitore può essere usato per personalizzare l'oggetto ENTRYPOINT
del contenitore, ovvero l'eseguibile chiamato all'avvio del contenitore. Per impostazione predefinita, per le compilazioni che creano un host di app, viene impostato come ContainerEntrypoint
. Per le compilazioni che non creano un eseguibile, dotnet path/to/app.dll
viene usato come ContainerEntrypoint
.
Il nodo ContainerEntrypoint
ha un singolo attributo:
Include
: comando, opzione o argomento da usare nel comandoContainerEntrypoint
.
Si consideri ad esempio il gruppo di elementi di progetto .NET di esempio seguente:
<ItemGroup Label="Entrypoint Assignment">
<!-- This is how you would start the dotnet ef tool in your container -->
<ContainerEntrypoint Include="dotnet" />
<ContainerEntrypoint Include="ef" />
<!-- This shorthand syntax means the same thing.
Note the semicolon separating the tokens. -->
<ContainerEntrypoint Include="dotnet;ef" />
</ItemGroup>
ContainerEntrypointArgs
Il nodo argomenti del punto di ingresso del contenitore controlla gli argomenti predefiniti forniti a ContainerEntrypoint
. Questa operazione deve essere usata quando ContainerEntrypoint
è un programma che l'utente potrebbe voler usare autonomamente. Per impostazione predefinita, non viene creato alcun ContainerEntrypointArgs
per conto dell'utente.
Il nodo ContainerEntrypointArg
ha un singolo attributo:
Include
: opzione o argomento da applicare al comandoContainerEntrypoint
.
Si consideri il gruppo di elementi di progetto .NET di esempio seguente:
<ItemGroup>
<!-- Assuming the ContainerEntrypoint defined above,
this would be the way to update the database by
default, but let the user run a different EF command. -->
<ContainerEntrypointArgs Include="database" />
<ContainerEntrypointArgs Include="update" />
<!-- This is the shorthand syntax for the same idea -->
<ContainerEntrypointArgs Include="database;update" />
</ItemGroup>
Etichette dei contenitori predefinite
Le etichette vengono spesso usate per fornire metadati coerenti sulle immagini del contenitore. Questo pacchetto fornisce alcune etichette predefinite per incoraggiare una migliore manutenibilità delle immagini generate.
org.opencontainers.image.created
è impostato sul formato ISO 8601 dell'ora UTC correnteDateTime
.
Per altre informazioni, vedere Implementare le etichette convenzionali sopra l'infrastruttura di etichette esistente.
Pulire le risorse
In questo articolo è stato pubblicato un ruolo di lavoro .NET come immagine del contenitore. Se si vuole, eliminare questa risorsa. Usare il comando docker images
per visualizzare un elenco delle immagini installate.
docker images
Si consideri l'output di esempio seguente:
REPOSITORY TAG IMAGE ID CREATED SIZE
dotnet-worker-image 1.0.0 25aeb97a2e21 12 seconds ago 191MB
Suggerimento
I file di immagine possono essere di grandi dimensioni. In genere è consigliabile rimuovere i contenitori temporanei creati durante il test e lo sviluppo dell'app. Conservare invece le immagini di base con il runtime installato se si prevede di compilare altre immagini basate su quel runtime.
Per eliminare l'immagine, copiare l'ID immagine ed eseguire il comando docker image rm
:
docker image rm 25aeb97a2e21