Herramientas de contenedor de Visual Studio con ASP.NET Core

En Visual Studio 2017 y versiones posteriores, se pueden compilar, depurar y ejecutar aplicaciones ASP.NET Core incluidas en un contenedor para .NET Core. Se admiten contenedores de Windows y Linux.

Vea o descargue el código de ejemplo (cómo descargarlo)

Requisitos previos

Instalación y configuración

Para instalar Docker, primero revise la información de Docker Desktop for Windows: What to know before you install (Docker Desktop para Windows: información previa a la instalación). A continuación, instale Docker para Windows.

Las unidades compartidas de Docker para Windows deben configurarse para admitir la asignación y la depuración de volúmenes. Haga clic con el botón derecho en el icono de Docker de la bandeja del sistema, y seleccione Configuración y Unidades compartidas. Seleccione la unidad donde los archivos se almacenan en Docker. Haga clic en Aplicar.

Dialog to select local C drive sharing for containers

Sugerencia

Las versiones 15.6 y posteriores de Visual Studio 2017 le avisan si las unidades compartidas no están configuradas.

Agregar un proyecto a un contenedor de Docker

Para incluir un proyecto de ASP.NET Core en un contenedor, el proyecto debe ser para .NET Core. Se admiten contenedores de Linux y Windows.

Al agregar compatibilidad con Docker a un proyecto, elija un contenedor de Linux o Windows. El host de Docker debe ejecutar el mismo tipo de contenedor. Para cambiar el tipo de contenedor en la instancia de Docker en ejecución, haga clic con el botón derecho en el icono de Docker en la bandeja del sistema y elija Switch to Windows containers... (Cambiar a contenedores Windows) o Switch to Linux containers... (Cambiar a contenedores Linux).

Nueva aplicación

Al crear una nueva aplicación con las plantillas de proyecto Aplicación web ASP.NET Core, active la casilla Enable Docker Support (Habilitar compatibilidad con Docker):

Enable Docker Support checkbox

Si la plataforma de destino es .NET Core, la lista desplegable de SO permite la selección de un tipo de contenedor.

Aplicación existente

En los proyectos de ASP.NET Core para .NET Core, hay dos opciones para agregar compatibilidad con Docker mediante las herramientas. Abra el proyecto en Visual Studio y elija una de las siguientes opciones:

  • Seleccione Compatibilidad con Docker en el menú Proyecto.
  • Haga clic con el botón derecho en el proyecto, en el Explorador de soluciones, y seleccione Agregar>Compatibilidad con Docker.

Las herramientas de contenedor de Visual Studio no admiten la adición de Docker a un proyecto de ASP.NET Core existente para .NET Framework.

Información general sobre Dockerfile

Se agrega un Dockerfile, la receta para crear una imagen de Docker final, a la raíz del proyecto. Vea Dockerfile reference (Referencia de Dockerfile) para obtener una descripción de los comandos que contiene. Este Dockerfile en concreto usa una compilación de varias fases, con cuatro fases de compilación distintas y cada una con un nombre asignado:

FROM mcr.microsoft.com/dotnet/core/aspnet:2.1 AS base
WORKDIR /app
EXPOSE 59518
EXPOSE 44364

FROM mcr.microsoft.com/dotnet/core/sdk:2.1 AS build
WORKDIR /src
COPY HelloDockerTools/HelloDockerTools.csproj HelloDockerTools/
RUN dotnet restore HelloDockerTools/HelloDockerTools.csproj
COPY . .
WORKDIR /src/HelloDockerTools
RUN dotnet build HelloDockerTools.csproj -c Release -o /app

FROM build AS publish
RUN dotnet publish HelloDockerTools.csproj -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "HelloDockerTools.dll"]

La imagen de Dockerfile anterior incluye el runtime de ASP.NET Core y los paquetes NuGet. Los paquetes están compilados Just-In-Time (JIT) para mejorar el rendimiento de inicio.

Si la casilla Configurar para HTTPS del cuadro de diálogo del nuevo proyecto está marcada, Dockerfile expondrá dos puertos. Uno se utiliza para el tráfico HTTP, mientras que el otro se emplea para HTTPS. Si la casilla no está activada, se expone un único puerto (80) para el tráfico HTTP.

FROM microsoft/aspnetcore:2.0 AS base
WORKDIR /app
EXPOSE 80

FROM microsoft/aspnetcore-build:2.0 AS build
WORKDIR /src
COPY HelloDockerTools/HelloDockerTools.csproj HelloDockerTools/
RUN dotnet restore HelloDockerTools/HelloDockerTools.csproj
COPY . .
WORKDIR /src/HelloDockerTools
RUN dotnet build HelloDockerTools.csproj -c Release -o /app

FROM build AS publish
RUN dotnet publish HelloDockerTools.csproj -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "HelloDockerTools.dll"]

La imagen de Dockerfile anterior incluye los paquetes NuGet de ASP.NET Core, que se compilan cuando es necesario (JIT) para mejorar el rendimiento del inicio.

Agregar compatibilidad con un orquestador de contenedores a una aplicación

Visual Studio 2017, versiones 15.7 o anteriores, es compatible con Docker Compose como única solución de orquestación de contenedores. Los artefactos de Docker Compose se agregan mediante Agregar>Compatibilidad con Docker.

Visual Studio 2017, versiones 15.8 o posteriores, permite agregar una solución de orquestación de forma manual. Haga clic con el botón derecho en el Explorador de soluciones y seleccione Agregar>Compatibilidad con el orquestador de contenedores. Están disponibles las siguientes opciones:

Docker Compose

Las herramientas de contenedor de Visual Studio agregan un proyecto docker-compose a la solución con los archivos siguientes:

  • docker-compose.dcproj: archivo que representa el proyecto. Incluye un elemento <DockerTargetOS> en el que se especifica el sistema operativo que se utilizará.
  • .dockerignore: contiene una lista de los patrones de archivos y directorios que se excluirán al generar un contexto de compilación.
  • docker-compose.yml: archivo base de Docker Compose que se utiliza para definir la colección de imágenes compilada y ejecutada con docker-compose build y docker-compose run, respectivamente.
  • docker-compose.override.yml: archivo opcional que Docker Compose lee y que contiene las invalidaciones de configuración de los servicios. Visual Studio ejecuta docker-compose -f "docker-compose.yml" -f "docker-compose.override.yml" para combinar estos archivos.

El archivo docker-compose.yml hace referencia al nombre de la imagen que se crea al ejecutar el proyecto:

version: '3.4'

services:
  hellodockertools:
    image: ${DOCKER_REGISTRY}hellodockertools
    build:
      context: .
      dockerfile: HelloDockerTools/Dockerfile

En el ejemplo anterior, image: hellodockertools genera la imagen hellodockertools:dev cuando se ejecuta la aplicación en modo de depuración. La imagen hellodockertools:latest se genera cuando se ejecuta la aplicación en modo de versión.

Si tiene previsto colocar la imagen en el Registro, utilice el nombre de usuario de Docker Hub como prefijo, antes del nombre de imagen, por ejemplo, dockerhubusername/hellodockertools. También puede cambiar el nombre de la imagen para incluir la dirección URL del Registro privado (por ejemplo, privateregistry.domain.com/hellodockertools) según la configuración.

Si quiere un comportamiento diferente basado en la configuración de compilación (por ejemplo, Debug o Release), agregue archivos docker-compose específicos de la configuración. Los nombres de los archivos deben basarse en la configuración de compilación (por ejemplo, docker-compose.vs.debug.yml y docker-compose.vs.release.yml) y deben colocarse en la misma ubicación que el archivo docker-compose-override.yml.

Con los archivos de invalidación específicos de la configuración, puede especificar distintos valores de configuración (por ejemplo, variables de entorno o puntos de entrada) para las configuraciones de compilación de depuración y lanzamiento.

Para que Docker Compose muestre una opción para su ejecución en Visual Studio, el proyecto de Docker debe ser el proyecto de inicio.

Service Fabric

Además de los requisitos previos base, la solución de orquestación de Service Fabric presenta los siguientes requisitos previos:

Service Fabric no admite la ejecución de contenedores de Linux en el clúster de desarrollo local de Windows. Si el proyecto ya utiliza un contenedor de Linux, Visual Studio le solicitará que cambie a los contenedores de Windows.

Las herramientas de contenedor de Visual Studio permiten realizar las siguientes tareas:

  • Agregar un proyecto Aplicación de Service Fabric<nombre_proyecto>Aplicación a la solución.

  • Agregar un Dockerfile y un archivo .dockerignore al proyecto de ASP.NET Core. Si el proyecto de ASP.NET Core ya contiene un Dockerfile, se le cambiará el nombre a Dockerfile.original. A continuación, se creará un nuevo Dockerfile similar al siguiente:

    # See https://aka.ms/containerimagehelp for information on how to use Windows Server 1709 containers with Service Fabric.
    # FROM microsoft/aspnetcore:2.0-nanoserver-1709
    FROM microsoft/aspnetcore:2.0-nanoserver-sac2016
    ARG source
    WORKDIR /app
    COPY ${source:-obj/Docker/publish} .
    ENTRYPOINT ["dotnet", "HelloDockerTools.dll"]
    
  • Agregar un elemento <IsServiceFabricServiceProject> al archivo .csproj al proyecto de ASP.NET Core:

    <IsServiceFabricServiceProject>True</IsServiceFabricServiceProject>
    
  • Agregar una carpeta PackageRoot al proyecto de ASP.NET Core. La carpeta incluirá un manifiesto de servicio y las opciones de configuración del nuevo servicio.

Para obtener más información, consulte Implementación de una aplicación .NET de un contenedor de Windows en Azure Service Fabric.

Depuración

Seleccione Docker en la lista desplegable de depuración de la barra de herramientas y empiece a depurar la aplicación. La vista Docker de la ventana Salida muestra las acciones siguientes en curso:

  • Si todavía no está en la caché, se adquirirá la etiqueta 2.1-aspnetcore-runtime de la imagen del entorno de ejecución microsoft/dotnet. La imagen instala los entornos de ejecución de ASP.NET Core y .NET Core, así como las bibliotecas asociadas. Además, está optimizada para ejecutar aplicaciones ASP.NET Core en producción.
  • Dentro del contenedor, la variable de entorno ASPNETCORE_ENVIRONMENT se establece en Development.
  • Se exponen dos puertos asignados de forma dinámica: uno para HTTP y otro para HTTPS. El puerto asignado al localhost se puede asignar mediante el comando docker ps.
  • La aplicación se copia en el contenedor.
  • Se inicia el explorador predeterminado con el depurador asociado al contenedor, con el puerto asignado dinámicamente.

Seguidamente, se aplica la etiqueta dev a la imagen de Docker resultante de la aplicación. La imagen se basa en la etiqueta 2.1-aspnetcore-runtime de la imagen base microsoft/dotnet. Ejecute el comando docker images en la ventana Consola del Administrador de paquetes (PMC). Se muestran las imágenes en la máquina:

REPOSITORY        TAG                     IMAGE ID      CREATED         SIZE
hellodockertools  dev                     d72ce0f1dfe7  30 seconds ago  255MB
microsoft/dotnet  2.1-aspnetcore-runtime  fcc3887985bb  6 days ago      255MB
  • Se adquiere la imagen microsoft/aspnetcore en tiempo de ejecución (si todavía no está en la caché).
  • Dentro del contenedor, la variable de entorno ASPNETCORE_ENVIRONMENT se establece en Development.
  • Se expone el puerto 80 y se asigna a un puerto asignado dinámicamente para el host local. El puerto viene determinado por el host de Docker y se puede consultar con el comando docker ps.
  • La aplicación se copia en el contenedor.
  • Se inicia el explorador predeterminado con el depurador asociado al contenedor, con el puerto asignado dinámicamente.

Seguidamente, se aplica la etiqueta dev a la imagen de Docker resultante de la aplicación. La imagen se basa en la imagen base microsoft/aspnetcore. Ejecute el comando docker images en la ventana Consola del Administrador de paquetes (PMC). Se muestran las imágenes en la máquina:

REPOSITORY            TAG  IMAGE ID      CREATED        SIZE
hellodockertools      dev  5fafe5d1ad5b  4 minutes ago  347MB
microsoft/aspnetcore  2.0  c69d39472da9  13 days ago    347MB

Nota

La imagen dev carece del contenido de la aplicación, ya que las opciones de configuración de depuración utilizan el montaje de volúmenes para proporcionar la experiencia iterativa. Para insertar una imagen, use la configuración de versión.

Ejecute el comando docker ps en la PMC. Tenga en cuenta que la aplicación se ejecuta mediante el contenedor:

CONTAINER ID        IMAGE                  COMMAND                   CREATED             STATUS              PORTS                   NAMES
baf9a678c88d        hellodockertools:dev   "C:\\remote_debugge..."   21 seconds ago      Up 19 seconds       0.0.0.0:37630->80/tcp   dockercompose4642749010770307127_hellodockertools_1

Editar y continuar

Los cambios en archivos estáticos y vistas de Razor se actualizan automáticamente sin necesidad de ningún paso de compilación. Realice el cambio, guarde y actualice el explorador para ver la actualización.

Las modificaciones en los archivos de código requieren compilación y un reinicio de Kestrel dentro del contenedor. Después de realizar la modificación, use CTRL+F5 para realizar el proceso e iniciar la aplicación dentro del contenedor. El contenedor de Docker no se vuelve a compilar ni se detiene. Ejecute el comando docker ps en la PMC. Observe que el contenedor original se está ejecutando desde hace 10 minutos:

CONTAINER ID        IMAGE                  COMMAND                   CREATED             STATUS              PORTS                   NAMES
baf9a678c88d        hellodockertools:dev   "C:\\remote_debugge..."   10 minutes ago      Up 10 minutes       0.0.0.0:37630->80/tcp   dockercompose4642749010770307127_hellodockertools_1

Publicar imágenes de Docker

Una vez que se completa el ciclo de desarrollo y depuración de la aplicación, las herramientas de contenedor de Visual Studio ayudan a crear la imagen de producción de la aplicación. Cambie la lista desplegable de configuración a Versión y compile la aplicación. Si todavía no está en la caché, las herramientas obtendrán la imagen de compilación o publicación a partir de Docker Hub. Se generará una imagen con la etiqueta más reciente que se puede colocar en el Registro privado o Docker Hub.

Para consultar la lista de imágenes, ejecute el comando docker images en PMC. Esto genera una salida similar a la siguiente:

REPOSITORY        TAG                     IMAGE ID      CREATED             SIZE
hellodockertools  latest                  e3984a64230c  About a minute ago  258MB
hellodockertools  dev                     d72ce0f1dfe7  4 minutes ago       255MB
microsoft/dotnet  2.1-sdk                 9e243db15f91  6 days ago          1.7GB
microsoft/dotnet  2.1-aspnetcore-runtime  fcc3887985bb  6 days ago          255MB
REPOSITORY                  TAG     IMAGE ID      CREATED         SIZE
hellodockertools            latest  cd28f0d4abbd  12 seconds ago  349MB
hellodockertools            dev     5fafe5d1ad5b  23 minutes ago  347MB
microsoft/aspnetcore-build  2.0     7fed40fbb647  13 days ago     2.02GB
microsoft/aspnetcore        2.0     c69d39472da9  13 days ago     347MB

A partir de .NET Core 2.1, las imágenes microsoft/aspnetcore-build y microsoft/aspnetcore que figuran en la salida anterior se reemplazan por imágenes microsoft/dotnet. Para obtener más información, consulte el anuncio sobre la migración de los repositorios de Docker.

Nota

El comando docker images devuelve imágenes de intermediario con los nombres de repositorio y las etiquetas identificados como <ninguno> (no mencionado anteriormente). Estas imágenes sin nombre son creadas por el Dockerfile de compilación de varias fases. Mejoran la eficacia de la compilación de la imagen final y solo se vuelven a compilar las capas necesarias cuando se producen cambios. Cuando las imágenes de intermediario ya no sean necesarias, elimínelas mediante el comando docker rmi.

Podría esperarse que la imagen de producción o versión fuera más pequeña que la imagen dev. Debido a la asignación de volumen, el depurador y la aplicación se han ejecutado desde la máquina local y no dentro del contenedor. La imagen más reciente ha empaquetado el código de aplicación necesario para ejecutar la aplicación en un equipo host. Por tanto, la diferencia es el tamaño del código de aplicación.

Recursos adicionales