Inclusión de una aplicación .NET Core en un contenedor

Se aplica a: Windows Server 2022, Windows Server 2019, Windows Server 2016

En este tema se describe cómo empaquetar una aplicación .NET de ejemplo existente para implementarla como un contenedor de Windows, después de configurar el entorno, tal como se describe en Introducción: preparar Windows para contenedores y ejecutar el primer contenedor tal y como se describe en Ejecución del primer contenedor de Windows.

También necesitarás tener instalado el sistema de control de código fuente de Git en el equipo. Para instalarlo, visita Git.

Clonación del código de ejemplo de GitHub

Todo el código fuente de ejemplo del contenedor se mantiene en el repositorio git Virtualization-Documentation (conocido informalmente como repositorio) en una carpeta denominada windows-container-samples.

  1. Abre una sesión de PowerShell y cambia al directorio de la carpeta en la que quieres almacenar este repositorio. (También funcionan otros tipos de ventana de símbolo del sistema, pero los comandos de ejemplo usan PowerShell).

  2. Clona el repositorio en el directorio de trabajo actual:

    git clone https://github.com/MicrosoftDocs/Virtualization-Documentation.git
    
  3. Navega hasta el directorio de ejemplo que se encuentra en Virtualization-Documentation\windows-container-samples\asp-net-getting-started y crea una instancia de Dockerfile con los siguientes comandos.

    Una instancia de Dockerfile es como un archivo Make, es una lista de instrucciones que indican al motor del contenedor cómo crear la imagen del contenedor.

    # Navigate into the sample directory
    Set-Location -Path Virtualization-Documentation\windows-container-samples\asp-net-getting-started
    
    # Create the Dockerfile for our project
    New-Item -Name Dockerfile -ItemType file
    

Escribir en Dockerfile

Abre el Dockerfile que acabas de crear con el editor de texto que quieras y, a continuación, agrega el siguiente contenido:

FROM mcr.microsoft.com/dotnet/core/sdk:2.1 AS build-env
WORKDIR /app

COPY *.csproj ./
RUN dotnet restore

COPY . ./
RUN dotnet publish -c Release -o out

FROM mcr.microsoft.com/dotnet/core/aspnet:2.1
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "asp-net-getting-started.dll"]

Vamos a desglosarlo línea por línea y a explicar lo que es cada instrucción.

FROM mcr.microsoft.com/dotnet/core/sdk:2.1 AS build-env
WORKDIR /app

El primer grupo de líneas indica la imagen base sobre la que crearemos nuestro contenedor. Si el sistema local no tiene aún esta imagen, el docker intentará automáticamente obtenerla. mcr.microsoft.com/dotnet/core/sdk:2.1 viene empaquetado con el SDK de .NET Core 2.1 instalado, por lo que la tarea puede compilar proyectos de ASP .NET Core que tienen como destino la versión 2.1. La siguiente instrucción cambia el directorio de trabajo en el contenedor para que sea /app, por lo que todos los comandos que siguen a este se ejecutan en este contexto.

COPY *.csproj ./
RUN dotnet restore

A continuación, estas instrucciones copian los archivos. csproj en el directorio /app del contenedor build-env. Después de copiar este archivo, .NET lo leerá y obtendrá todas las dependencias y herramientas que nuestro proyecto necesita.

COPY . ./
RUN dotnet publish -c Release -o out

Una vez que .NET ha extraído todas las dependencias en el contenedor build-env, la siguiente instrucción copia todos los archivos de origen del proyecto en el contenedor. Después indicamos a .NET que publique nuestra aplicación con una configuración de lanzamiento y que especifique la ruta de acceso de salida.

La compilación debe realizarse correctamente. Ahora debemos compilar la imagen final.

Sugerencia

En esta guía de inicio rápido se compila un proyecto de .NET Core desde el origen. Al compilar imágenes de contenedor, se recomienda incluir solo la carga de producción y sus dependencias en la imagen de contenedor. No queremos que el SDK de .NET Core esté incluido en la imagen final porque solo necesitamos el tiempo de ejecución de .NET Core, por lo que se escribe el dockerfile para usar un contenedor temporal que está empaquetado con el SDK llamado build-env para compilar la aplicación.

FROM mcr.microsoft.com/dotnet/core/aspnet:2.1
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "asp-net-getting-started.dll"]

Dado que nuestra aplicación es ASP.NET, especificamos una imagen con este tiempo de ejecución incluido. Después copiamos todos los archivos del directorio de salida de nuestro contenedor temporal en nuestro contenedor final. Configuramos el contenedor para que se ejecute con nuestra nueva aplicación como punto de entrada cuando se inicie el contenedor.

Hemos escrito el dockerfile para realizar una de compilación en varias fases. Cuando se ejecuta dockerfile, usará el contenedor temporal, build-env, con el SDK de .NET Core 2.1 para compilar la aplicación de ejemplo y, a continuación, copiar los archivos binarios de salida en otro contenedor que solo contenga el tiempo de ejecución de .NET Core 2.1 para minimizar el tamaño del contenedor final.

Compilar y ejecutar la aplicación

Con el Dockerfile escrito, podemos apuntar a Docker en nuestro Dockerfile e indicarle que compile y ejecute la imagen:

  1. En una ventana del símbolo del sistema, navega hasta el directorio donde reside el dockerfile y, a continuación, ejecuta el comando docker build para compilar el contenedor desde Dockerfile.

    docker build -t my-asp-app .
    
  2. Para ejecutar el contenedor recién creado, ejecuta el comando docker run.

    docker run -d -p 5000:80 --name myapp my-asp-app
    

    Vamos a analizar minuciosamente este comando:

    • -d indica a Docker que ejecute el contenedor "detached", lo que significa que no hay ninguna consola enlazada a la consola dentro del contenedor. El contenedor se ejecuta en segundo plano.
    • -p 5000:80 indica a Docker que asigne el puerto 5000 en el host al puerto 80 del contenedor. Cada contenedor obtiene su propia dirección IP. ASP .NET escucha de forma predeterminada en el puerto 80. La asignación de puertos nos permite ir a la dirección IP del host en el puerto asignado y Docker reenviará todo el tráfico al puerto de destino dentro del contenedor.
    • --name myapp indica a Docker que proporcione a este contenedor un nombre adecuado para consultar (en lugar de tener que buscar el id. del contenedor asignado en tiempo de ejecución por Docker).
    • my-asp-app es la imagen que queremos que ejecute Docker. Esta es la imagen de contenedor que se genera como culminación del proceso docker build.
  3. Abra un explorador web y vaya hasta http://localhost:5000 para ver la aplicación en el contenedor, tal como se muestra en esta captura de pantalla:

    Página web de ASP.NET Core, que se ejecuta desde localhost de un contenedor

Pasos siguientes

  1. El siguiente paso consiste en publicar la aplicación web de ASP.NET en contenedor en un registro privado mediante Azure Container Registry. Esto te permite implementarla en tu organización.

    Cuando llegues a la sección donde se inserta la imagen de contenedor en el registro, especifica el nombre de la aplicación ASP.NET que acabas de empaquetar (my-asp-app) junto con el registro de contenedor (por ejemplo: contoso-container-registry):

    docker tag my-asp-app contoso-container-registry.azurecr.io/my-asp-app:v1
    

    Para ver más ejemplos de aplicaciones y sus dockerfiles asociados, consulta ejemplos de contenedores adicionales.

  2. Una vez que hayas publicado la aplicación en el registro de contenedor, el paso siguiente sería implementar la aplicación en un clúster de Kubernetes que crees con Azure Kubernetes Service.