Inclusión de una aplicación .NET en un contenedor mediante dotnet publish
Los contenedores tienen muchas características y ventajas, como ser una infraestructura inmutable, proporcionar una arquitectura portátil y permitir la escalabilidad. La imagen puede usarse para crear contenedores para un entorno de desarrollo local, una nube privada o una nube pública. En este tutorial aprenderá a incluir una aplicación .NET en un contenedor usando el comando dotnet publish.
Requisitos previos
Instale estos requisitos previos:
- SDK de .NET 8 y versiones posteriores
Si tiene instalado .NET, use el comandodotnet --info
para determinar el SDK que está usando. - Docker Community Edition
- SDK de .NET 7 (y posteriores)
Si tiene instalado .NET, use el comandodotnet --info
para determinar el SDK que está usando. - Docker Community Edition
Además de estos requisitos previos, se recomienda estar familiarizado con los servicios de trabajo de .NET.
Creación de aplicaciones .NET
Necesita incluir una aplicación .NET en un contenedor. Empezaremos creando una aplicación a partir de una plantilla. Abra el terminal, cree una carpeta de trabajo (sample-directory) si aún no lo ha hecho y cambie de directorio para situarse en esa carpeta. En la carpeta de trabajo, ejecute el siguiente comando para crear un proyecto en un subdirectorio llamado Worker:
dotnet new worker -o Worker -n DotNet.ContainerImage
El árbol de carpetas tiene un aspecto similar al siguiente:
📁 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
El comando dotnet new
crea una carpeta llamada Worker y genera un servicio de trabajo que, cuando se ejecuta, registra un mensaje cada segundo. En la sesión de terminal, cambie de directorio y vaya a la carpeta Worker. Use el comando dotnet run
para iniciar la aplicación.
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...
La plantilla de trabajo se repite en bucle indefinidamente. Use el comando Cancelar Ctrl+C para detenerla.
Adición del paquete NuGet
Actualmente, es necesario el paquete NuGet Microsoft.NET.Build.Containers para publicar proyectos que no son web como un contenedor. Para agregar el paquete NuGet Microsoft.NET.Build.Containers
a la plantilla de trabajo, ejecute el siguiente comando dotnet add package:
dotnet add package Microsoft.NET.Build.Containers
Sugerencia
Si va a compilar una aplicación web mediante el SDK de .NET 7.0.300 o una versión posterior, el paquete ya no es necesario. El SDK ya contiene la misma funcionalidad.
Establecimiento del nombre de la imagen de contenedor
Al publicar una aplicación como un contenedor, hay varias opciones de configuración disponibles.
El nombre de la imagen de contenedor es de forma predeterminada el nombre AssemblyName
del proyecto. Si ese nombre no es válido como nombre de imagen de contenedor, se puede invalidar especificando un nombre ContainerRepository
, como se muestra en el archivo del proyecto siguiente:
<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>
Para obtener más información, consulte ContainerRepository.
El nombre de la imagen de contenedor es de forma predeterminada el nombre AssemblyName
del proyecto. Si ese nombre no es válido como un nombre de imagen de contenedor, puede invalidarlo especificando (ContainerImageName
obsoleto) o el ContainerRepository
preferido, como se muestra en el siguiente archivo de proyecto:
<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>
Para obtener más información, consulte ContainerImageName.
Publicación de una aplicación .NET
Para publicar la aplicación .NET como un contenedor, use el siguiente comando dotnet publish:
dotnet publish --os linux --arch x64 /t:PublishContainer -c Release
El comando de la CLI de .NET anterior publica la aplicación como un contenedor con las siguientes características:
- Tiene Linux como sistema operativo de destino (
--os linux
). - Especifica una arquitectura x64 (
--arch x64
). - Usa la configuración de versión (
-c Release
).
Importante
Para crear el contenedor localmente, el demonio de Docker debe estar en ejecución. Si no lo está cuando intente publicar la aplicación como un contenedor, experimentará un error similar al siguiente:
..\build\Microsoft.NET.Build.Containers.targets(66,9): error MSB4018:
The "CreateNewImage" task failed unexpectedly. [..\Worker\DotNet.ContainerImage.csproj]
Sugerencia
En función del tipo de aplicación que se va a incluir en un contenedor, los modificadores de línea de comandos (opciones) pueden variar. Por ejemplo, el argumento /t:PublishContainer
es necesario únicamente con aplicaciones .NET que no son web, como las plantillas console
y worker
. En las plantillas web, reemplace el argumento /t:PublishContainer
por -p:PublishProfile=DefaultContainer
. Para obtener más información, vea Creación de contenedores del SDK de .NET, problema n.º 141.
El comando genera una salida similar a la del ejemplo:
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
Este comando compila la aplicación de trabajo en la carpeta publish e inserta el contenedor en el registro de Docker local.
Configuración de la imagen de contenedor
Muchos aspectos del contenedor generado se pueden controlar mediante propiedades de MSBuild. En general, si puede usar un comando en un Dockerfile para establecer alguna configuración, podrá hacer lo mismo a través de MSBuild.
Nota:
Las únicas excepciones a esto son los comandos RUN
. Debido a la forma en que los contenedores se compilan, no se pueden emular. Si necesita esta funcionalidad, deberá usar un Dockerfile para compilar las imágenes de contenedor.
ContainerArchiveOutputPath
A partir de .NET 8, puede crear un contenedor directamente como archivo tar.gz. Esta característica es útil si el flujo de trabajo no es sencillo y requiere que, por ejemplo, ejecute una herramienta de examen sobre las imágenes antes de insertarlas. Una vez creado el archivo, puede moverlo, examinarlo o cargarlo en una cadena de herramientas local de Docker.
Para publicar en un archivo, agregue la propiedad ContainerArchiveOutputPath
al comando dotnet publish
, por ejemplo:
dotnet publish \
-p PublishProfile=DefaultContainer \
-p ContainerArchiveOutputPath=./images/sdk-container-demo.tar.gz
Puede especificar un nombre de carpeta o una ruta de acceso con un nombre de archivo específico. Si especifica el nombre de carpeta, el nombre de archivo generado para el archivo del archivo de imágenes será $(ContainerRepository).tar.gz
. Estos archivos pueden contener varias etiquetas dentro de ellos, solo cuando se crea un solo archivo para todos los ContainerImageTags
.
Configuración de nomenclatura de imágenes de contenedor
Las imágenes de contenedor siguen una convención de nomenclatura específica. El nombre de la imagen se compone de varias partes, el registro, el puerto opcional, el repositorio y la etiqueta y la familia opcionales.
REGISTRY[:PORT]/REPOSITORY[:TAG[-FAMILY]]
Por ejemplo, considere el nombre de imagen completo mcr.microsoft.com/dotnet/runtime:8.0-alpine
:
mcr.microsoft.com
es el registro (y en este caso representa el registro de contenedor de Microsoft).dotnet/runtime
es el repositorio (pero algunos consideran este comouser/repository
).8.0-alpine
es la etiqueta y la familia (la familia es un especificador opcional que ayuda a eliminar la ambigüedad del empaquetado del sistema operativo).
Algunas propiedades descritas en las secciones siguientes corresponden a la administración de partes del nombre de imagen generado. Tenga en cuenta la tabla siguiente que asigna la relación entre el nombre de la imagen y las propiedades de compilación:
Elemento nombre de imagen | Propiedad de MSBuild | Valores de ejemplo |
---|---|---|
REGISTRY[:PORT] |
ContainerRegistry |
mcr.microsoft.com:443 |
PORT |
ContainerPort |
:443 |
REPOSITORY |
ContainerRepository |
dotnet/runtime |
TAG |
ContainerImageTag |
8.0 |
FAMILY |
ContainerFamily |
-alpine |
Elemento nombre de imagen | Propiedad de MSBuild | Valores de ejemplo |
---|---|---|
REGISTRY[:PORT] |
ContainerRegistry |
mcr.microsoft.com:443 |
PORT |
ContainerPort |
:443 |
REPOSITORY |
ContainerImageName |
dotnet/runtime |
TAG |
ContainerImageTag |
8.0 |
En las secciones siguientes se describen las distintas propiedades que se pueden usar para controlar la imagen de contenedor generada.
ContainerBaseImage
La propiedad de imagen base del contenedor controla la imagen que se usa como base de la imagen. De forma predeterminada, se deducen los siguientes valores en función de las propiedades del proyecto:
- Si el proyecto es autocontenido, se usa la imagen
mcr.microsoft.com/dotnet/runtime-deps
como imagen base. - Si el proyecto es un proyecto de ASP.NET Core, se usa la imagen
mcr.microsoft.com/dotnet/aspnet
como imagen base. - De lo contrario, se usa la imagen
mcr.microsoft.com/dotnet/runtime
.
La etiqueta de la imagen se deduce para que sea el componente numérico del TargetFramework
elegido. Por ejemplo, un proyecto que tiene como destino net6.0
da como resultado la etiqueta 6.0
de la imagen base deducida, y un proyecto con net7.0-linux
como destino usa la etiqueta 7.0
, etc.
Si establece un valor aquí, debe establecer el nombre completo de la imagen que se usará como base, incluida cualquier etiqueta de su preferencia:
<PropertyGroup>
<ContainerBaseImage>mcr.microsoft.com/dotnet/runtime:8.0</ContainerBaseImage>
</PropertyGroup>
<PropertyGroup>
<ContainerBaseImage>mcr.microsoft.com/dotnet/runtime:7.0</ContainerBaseImage>
</PropertyGroup>
ContainerFamily
A partir de .NET 8, puede usar la propiedad de MSBuild ContainerFamily
para elegir una familia diferente de imágenes de contenedor proporcionadas por Microsoft como imagen base para la aplicación. Cuando se establece, este valor se anexa al final de la etiqueta específica de TFM seleccionada, cambiando la etiqueta proporcionada. Por ejemplo, para usar las variantes de Alpine Linux de las imágenes base de .NET, puede establecer ContainerFamily
en alpine
:
<PropertyGroup>
<ContainerFamily>alpine</ContainerFamily>
</PropertyGroup>
La configuración del proyecto anterior da como resultado una etiqueta final de 8.0-alpine
para una aplicación con .NET 8 como destino.
Este campo se introduce de forma libre y, a menudo, se puede usar para seleccionar diferentes distribuciones del sistema operativo, configuraciones de paquetes predeterminadas o cualquier otro tipo de cambios en una imagen base. Se omite este campo al establecerse ContainerBaseImage
. Para obtener más información, vea Imágenes de contenedor .NET.
ContainerRuntimeIdentifier
La propiedad de identificador del entorno de ejecución del contenedor controla el sistema operativo y la arquitectura que usa el contenedor si ContainerBaseImage admite más de una plataforma. Por ejemplo, la imagen mcr.microsoft.com/dotnet/runtime
actualmente admite las imágenes linux-x64
, linux-arm
, linux-arm64
y win10-x64
con la misma etiqueta, por lo que las herramientas necesitan una manera de indicarles cuál de estas versiones desea usar. De forma predeterminada, se establece en el valor de RuntimeIdentifier
que eligió al publicar el contenedor. Rara vez es necesario establecer esta propiedad de forma explícita. En su lugar, utilice la opción -r
para el comando dotnet publish
. Si la imagen que elige no es compatible con el RuntimeIdentifier
que había elegido, esto dará como resultado un error que describe los runtimeIdentifiers que la imagen admite.
Siempre puede establecer la propiedad ContainerBaseImage
en un nombre de imagen completo, incluida la etiqueta, para no tener que usar esta propiedad.
<PropertyGroup>
<ContainerRuntimeIdentifier>linux-arm64</ContainerRuntimeIdentifier>
</PropertyGroup>
Para obtener más información sobre los identificadores del entorno de ejecución admitidos por .NET, consulte Catálogo RID.
ContainerRegistry
La propiedad del registro de contenedor controla el registro del destino, es decir, dónde se va a insertar la imagen recién creada. De forma predeterminada, se inserta en el demonio de Docker local, pero también puede especificar un registro remoto. Cuando se usa un registro remoto que requiere autenticación, se utilizan los conocidos mecanismos de docker login
para ello. Para obtener información más detallada, consulte Autenticación en registros de contenedor. Para obtener un ejemplo concreto del uso de esta propiedad, vea el siguiente ejemplo XML:
<PropertyGroup>
<ContainerRegistry>registry.mycorp.com:1234</ContainerRegistry>
</PropertyGroup>
Esta herramienta permite publicar en cualquier registro que admita Docker Registry HTTP API V2. Esto incluye los siguientes registros de forma explícita (y probablemente muchos más de forma implícita):
- Azure Container Registry
- Amazon Elastic Container Registry
- Google Artifact Registry
- Docker Hub
- GitHub Packages
- GitLab Container Registry
- Quay.io
Para obtener instrucciones sobre cómo trabajar con estos registros, consulte las notas específicas de cada registro.
ContainerRepository
El repositorio de contenedores es el nombre de la imagen en sí, por ejemplo, dotnet/runtime
o my-app
. De forma predeterminada, se usa el nombre AssemblyName
del proyecto.
<PropertyGroup>
<ContainerRepository>my-app</ContainerRepository>
</PropertyGroup>
ContainerImageName
El nombre de la imagen de contenedor controla el nombre de la imagen en sí, por ejemplo, dotnet/runtime
o my-app
. De forma predeterminada, se usa el nombre AssemblyName
del proyecto.
<PropertyGroup>
<ContainerImageName>my-app</ContainerImageName>
</PropertyGroup>
Nota:
A partir de .NET 8, ContainerImageName
queda obsoleto en favor de ContainerRepository
.
Los nombres de imagen constan de uno o varios segmentos delimitados por barras diagonales que solo pueden contener caracteres alfanuméricos en minúscula, puntos, caracteres de subrayado y guiones, y deben comenzar con una letra o un número. El uso de cualquier otro carácter producirá un error.
ContainerImageTag(s)
La propiedad de etiqueta de imagen de contenedor controla las etiquetas que se generan relativas a la imagen. Para especificar una sola etiqueta, use ContainerImageTag
y, para varias etiquetas, use ContainerImageTags
.
Importante
Cuando use ContainerImageTags
, terminará con varias imágenes, una por etiqueta única.
Las etiquetas se suelen usar para hacer referencia a distintas versiones de una aplicación, pero también pueden hacer referencia a distribuciones de sistema operativo diferentes o, incluso, a configuraciones diferentes.
A partir de .NET 8, cuando no se proporciona una etiqueta, el valor predeterminado es latest
.
De forma predeterminada, se usa el valor de Version
del proyecto como valor de etiqueta.
Para invalidar el valor predeterminado, especifique una de las siguientes opciones:
<PropertyGroup>
<ContainerImageTag>1.2.3-alpha2</ContainerImageTag>
</PropertyGroup>
Para especificar varias etiquetas, use un conjunto de etiquetas delimitadas por punto y coma en la propiedad ContainerImageTags
(similar a establecer varios TargetFrameworks
):
<PropertyGroup>
<ContainerImageTags>1.2.3-alpha2;latest</ContainerImageTags>
</PropertyGroup>
Las etiquetas solo pueden contener un máximo de 127 caracteres alfanuméricos, puntos, caracteres de subrayado y guiones. Deben empezar por un carácter alfanumérico o por un carácter de subrayado. El uso de cualquier otro formato producirá un error.
Nota:
Al usar ContainerImageTags
, las etiquetas se delimitan mediante un carácter ;
. Si llama a dotnet publish
desde la línea de comandos (como sucede con la mayoría de los entornos de CI/CD), deberá ajustar de forma externa los valores en una '
simple y de forma interna con comillas dobles "
, por ejemplo (='"tag-1;tag-2"'
). Tenga en cuenta el siguiente comando dotnet publish
:
dotnet publish -p ContainerImageTags='"1.2.3-alpha2;latest"'
Esto da como resultado que se generen dos imágenes: my-app:1.2.3-alpha2
y my-app:latest
.
Sugerencia
Si experimenta problemas con la propiedad ContainerImageTags
, considere la posibilidad de determinar el ámbito de una variable de entorno ContainerImageTags
en su lugar:
ContainerImageTags='1.2.3;latest' dotnet publish
ContainerLabel
La etiqueta de contenedor agrega una etiqueta de metadatos al contenedor. Las etiquetas no tienen ningún impacto en el contenedor en tiempo de ejecución, pero suelen usarse para almacenar los metadatos de versión y creación para que puedan usarse en los exámenes de seguridad y en otras herramientas de infraestructura. Puede especificar cualquier número de etiquetas de contenedor.
El nodo ContainerLabel
tiene dos atributos:
Include
: clave de la etiqueta.Value
: valor de la etiqueta (puede estar vacío).
<ItemGroup>
<ContainerLabel Include="org.contoso.businessunit" Value="contoso-university" />
</ItemGroup>
Para obtener una lista de etiquetas creadas de forma predeterminada, vea Etiquetas de contenedor predeterminadas.
Configuración de la ejecución de contenedor
Para controlar la ejecución de contenedor, puede usar las siguientes propiedades de MSBuild.
ContainerWorkingDirectory
El nodo del directorio de trabajo del contenedor controla el directorio de trabajo del contenedor, el directorio en el que se ejecutan los comandos si no se ejecuta ningún otro comando.
De forma predeterminada, se usa el valor del directorio /app
como directorio de trabajo.
<PropertyGroup>
<ContainerWorkingDirectory>/bin</ContainerWorkingDirectory>
</PropertyGroup>
ContainerPort
El puerto de contenedor agrega puertos TCP o UDP a la lista de puertos conocidos del contenedor. Esto permite que los entornos de ejecución del contenedor, como Docker, asignen estos puertos automáticamente al equipo host. Esto se suele usar como documentación del contenedor, pero también se puede usar para habilitar la asignación automática de puertos.
El nodo ContainerPort
tiene dos atributos:
Include
: número de puerto que se va a exponer.Type
: el valor predeterminado estcp
. Los valores válidos sontcp
oudp
.
<ItemGroup>
<ContainerPort Include="80" Type="tcp" />
</ItemGroup>
A partir de .NET 8, se infiere ContainerPort
cuando no se proporciona explícitamente en función de varias variables de entorno de ASP.NET conocidas:
ASPNETCORE_URLS
ASPNETCORE_HTTP_PORTS
ASPNETCORE_HTTPS_PORTS
Si estas variables de entorno están presentes, sus valores se analizarán y convertirán en asignaciones de puertos TCP. Estas variables de entorno se leen de la imagen base, si está presente, o de las variables de entorno definidas en el proyecto a través de elementos ContainerEnvironmentVariable
. Para obtener más información, consulte ContainerEnvironmentVariable.
ContainerEnvironmentVariable
El nodo de variable de entorno de contenedor permite agregar variables de entorno al contenedor. Las variables de entorno son accesibles de inmediato para la aplicación que se ejecuta en el contenedor, y a menudo se usan para cambiar el comportamiento en tiempo de ejecución de la aplicación en ejecución.
El nodo ContainerEnvironmentVariable
tiene dos atributos:
Include
: nombre de la variable de entorno.Value
: valor de la variable de entorno.
<ItemGroup>
<ContainerEnvironmentVariable Include="LOGGER_VERBOSITY" Value="Trace" />
</ItemGroup>
Para obtener más información, vea Variables de entorno.
Configuración de comandos de contenedor
De forma predeterminada, las herramientas de contenedor inician la aplicación mediante el archivo binario AppHost generado de la aplicación (si la aplicación usa una instancia de AppHost), o bien el comando dotnet
más el archivo DLL de la aplicación.
Sin embargo, puede controlar cómo se ejecuta la aplicación mediante una combinación de ContainerAppCommand
, ContainerAppCommandArgs
, ContainerDefaultArgs
y ContainerAppCommandInstruction
.
Estos distintos puntos de configuración existen porque las distintas imágenes base usan combinaciones diferentes de las propiedades ENTRYPOINT
y COMMAND
del contenedor, y desea poder admitirlos todos. Los valores predeterminados deberían poder usarse para la mayoría de las aplicaciones, pero si quiere personalizar el comportamiento de inicio de la aplicación, debe:
- Identificar el archivo binario que se va a ejecutar y establecerlo como
ContainerAppCommand
- Identificar qué argumentos son necesarios para que se ejecute la aplicación y establecerlos como
ContainerAppCommandArgs
- Identificar qué argumentos (si los hay) son opcionales y podrían invalidarse por parte de un usuario y establecerlos como
ContainerDefaultArgs
- Establezca
ContainerAppCommandInstruction
enDefaultArgs
.
Para obtener más información, consulte los siguientes elementos de configuración.
ContainerAppCommand
El elemento de configuración del comando de la aplicación es el punto de entrada lógico de la aplicación. Para la mayoría de las aplicaciones, es AppHost, el archivo binario ejecutable generado de la aplicación. Si la aplicación no genera una instancia de AppHost, este comando normalmente será dotnet <your project dll>
. Estos valores se aplican después de cualquier elemento ENTRYPOINT
en el contenedor base o directamente si no se define ningún elemento ENTRYPOINT
.
La configuración ContainerAppCommand
tiene una sola propiedad Include
, que representa el comando, la opción o el argumento que se va a usar en el comando 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
Este elemento de configuración de argumentos del comando de la aplicación representa los argumentos lógicamente necesarios para la aplicación que se deben aplicar a ContainerAppCommand
. De manera predeterminada, ninguno se genera para una aplicación. Cuando están presentes, los argumentos se aplican al contenedor cuando se ejecuta.
La configuración ContainerAppCommandArgs
tiene una sola propiedad Include
, que representa la opción o argumento que se va a aplicar 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
Este elemento de configuración de argumentos predeterminado representa los argumentos que puede invalidar el usuario para la aplicación. Esta es una buena manera de proporcionar valores predeterminados que la aplicación podría necesitar para ejecutarse de una manera que facilite su inicio y, al mismo tiempo, su personalización.
La configuración ContainerDefaultArgs
tiene una sola propiedad Include
, que representa la opción o argumento que se va a aplicar 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 configuración de instrucciones del comando de la aplicación ayuda a controlar el modo en que se combinan ContainerEntrypoint
, ContainerEntrypointArgs
, ContainerAppCommand
, ContainerAppCommandArgs
y ContainerDefaultArgs
para formar el comando final que se ejecuta en el contenedor. Esto depende en gran medida de si un elemento ENTRYPOINT
está presente en la imagen base. Esta propiedad adopta uno de estos tres valores: "DefaultArgs"
, "Entrypoint"
o "None"
.
Entrypoint
:- En este modo,
ContainerAppCommand
,ContainerAppCommandArgs
yContainerDefaultArgs
definen el elemento entrypoint.
- En este modo,
None
:- En este modo,
ContainerEntrypoint
,ContainerEntrypointArgs
yContainerDefaultArgs
definen el elemento entrypoint.
- En este modo,
DefaultArgs
:- Este es el modo más complejo (si ninguno de los elementos
ContainerEntrypoint[Args]
está presente,ContainerAppCommand[Args]
yContainerDefaultArgs
se usan para crear el elemento entrypoint y el comando. El elemento entrypoint de la imagen base para las imágenes base que lo tienen codificado de forma rígida endotnet
o/usr/bin/dotnet
se omite para que tenga un control total. - Si tanto
ContainerEntrypoint
comoContainerAppCommand
están presentes,ContainerEntrypoint
se convierte en el elemento entrypoint yContainerAppCommand
se convierte en el comando.
- Este es el modo más complejo (si ninguno de los elementos
Nota:
Los elementos de configuración ContainerEntrypoint
y ContainerEntrypointArgs
han quedado en desuso desde .NET 8.
Importante
Esto es para los usuarios avanzados: la mayoría de las aplicaciones no deberían tener que personalizar su elemento entrypoint hasta este grado. Para obtener más información y si desea proporcionar casos de uso para sus escenarios, consulte las discusiones sobre compilaciones de contenedor del SDK de .NET en GitHub.
ContainerUser
La propiedad de configuración de usuario controla el usuario predeterminado con el que se ejecuta el contenedor. A menudo se usa para ejecutar el contenedor como usuario sin raíz, que es un procedimiento recomendado de seguridad. Hay algunas restricciones para que esta configuración que deben tenerse en cuenta:
- Puede tomar diversas formas: nombre de usuario, identificadores de usuario de Linux, nombre de grupo, identificador de grupo de Linux,
username:groupname
y otras variantes de identificador. - No está confirmado que el usuario o grupo especificado exista en la imagen.
- Cambiar el usuario puede modificar el comportamiento de la aplicación, especialmente en lo que respecta a cosas como los permisos del sistema de archivos.
El valor predeterminado de este campo varía según el TFM del proyecto y el sistema operativo de destino:
- Si usa como destino .NET 8 o versiones posteriores y las imágenes en tiempo de ejecución de Microsoft:
- en Linux, se usa el usuario sin raíz
app
(aunque su identificador de usuario le hace referencia) - en Windows, se usa el usuario sin raíz
ContainerUser
- en Linux, se usa el usuario sin raíz
- De lo contrario, no se usa ningún valor predeterminado
ContainerUser
<PropertyGroup>
<ContainerUser>my-existing-app-user</ContainerUser>
</PropertyGroup>
Sugerencia
La variable de entorno APP_UID
se usa para establecer la información de usuario en el contenedor. Este valor puede provenir de variables de entorno definidas en la imagen base (como las imágenes de Microsoft .NET) o puede establecerlo usted mismo a través de la sintaxis ContainerEnvironmentVariable
.
Sin embargo, puede controlar cómo se ejecuta la aplicación mediante ContainerEntrypoint
y ContainerEntrypointArgs
.
ContainerEntrypoint
El punto de entrada del contenedor se puede usar para personalizar el objeto ENTRYPOINT
del contenedor, que es el ejecutable al que se llama cuando se inicia el contenedor. De forma predeterminada, en las compilaciones que crean un host de aplicación, se establece como ContainerEntrypoint
. En las compilaciones que no crean un archivo ejecutable, dotnet path/to/app.dll
se usa como ContainerEntrypoint
.
El nodo ContainerEntrypoint
tiene un único atributo:
Include
: comando, opción o argumento que se va a usar en el comandoContainerEntrypoint
.
Veamos el siguiente ejemplo de grupo de elementos de proyecto de .NET:
<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
El nodo de argumentos de punto de entrada de contenedor controla los argumentos predeterminados proporcionados a ContainerEntrypoint
. Esto debe usarse cuando ContainerEntrypoint
sea un programa que el usuario podría querer usar por sí mismo. De forma predeterminada, no se crean ContainerEntrypointArgs
en su nombre.
El nodo ContainerEntrypointArg
tiene un único atributo:
Include
: opción o argumento que se va a aplicar al comandoContainerEntrypoint
.
Veamos el siguiente ejemplo de grupo de elementos de proyecto de .NET:
<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>
Etiquetas de contenedor predeterminadas
Las etiquetas se suelen usar para proporcionar unos metadatos coherentes en imágenes de contenedor. Este paquete proporciona algunas etiquetas predeterminadas para propiciar una mejor capacidad de mantenimiento de las imágenes generadas.
org.opencontainers.image.created
se establece en el formato ISO 8601 delDateTime
UTC actual.
Para obtener más información, vea Implementación de etiquetas convencionales sobre la infraestructura de etiquetas existente.
Limpieza de recursos
En este artículo, ha publicado un trabajo de .NET como una imagen de contenedor. Si lo desea, elimine este recurso. Use el comando docker images
para ver una lista de las imágenes instaladas.
docker images
Considere la siguiente salida de ejemplo:
REPOSITORY TAG IMAGE ID CREATED SIZE
dotnet-worker-image 1.0.0 25aeb97a2e21 12 seconds ago 191MB
Sugerencia
Los archivos de imagen pueden ser grandes. Por lo general, quitaría los contenedores temporales que creó al probar y desarrollar la aplicación. Habitualmente, estas imágenes base se conservan con el runtime instalado si se planea crear otras imágenes basadas en ese runtime.
Para eliminar la imagen, copie el identificador de la imagen y ejecute el comando docker image rm
:
docker image rm 25aeb97a2e21
Pasos siguientes
- Anuncio de la compatibilidad con contenedores integrada en el SDK de .NET
- Tutorial: Inclusión de una aplicación .NET en un contenedor
- Imágenes de contenedor de .NET
- Revise los servicios de Azure que admiten contenedores
- Lea sobre los comandos de Dockerfile
- Explore las herramientas de contenedor de Visual Studio