Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este tutorial, aprenderá a administrar más de un contenedor y a comunicarse entre ellos al usar Herramientas de contenedor en Visual Studio. La administración de varios contenedores requiere orquestación de contenedores y requiere un orquestador como Docker Compose. Para estos procedimientos, se usa Docker Compose. Docker Compose es ideal para las pruebas y la depuración locales durante el ciclo de desarrollo.
El ejemplo completado que crea en este tutorial se puede encontrar en GitHub en https://github.com/MicrosoftDocs/vs-tutorial-samples en la carpeta docker/ComposeSample.
Prerrequisitos
- Docker Desktop
- Visual Studio con la ASP.NET y el desarrollo web, la carga de trabajo desarrollo de Azure o la carga de trabajo desarrollo multiplataforma de .NET instalada. Esta instalación incluye el SDK de .NET.
- Docker Desktop
- Visual Studio con la ASP.NET y el desarrollo web, la carga de trabajo desarrollo de Azure o la carga de trabajo desarrollo multiplataforma de .NET instalada. Esta instalación incluye el SDK de .NET.
Creación de un proyecto de aplicación web
En Visual Studio, cree un proyecto de ASP.NET Core Web App llamado WebFrontEndpara crear una aplicación web con páginas Razor.
No seleccione Habilitar compatibilidad con contenedores. Agregue compatibilidad con contenedores más adelante en el proceso.
Creación de un proyecto de API web
Agregue un proyecto a la misma solución y llámelo MyWebAPI. Seleccione API como tipo de proyecto y desactive la casilla de Configure for HTTPS (Configurar para HTTPS).
Nota
En este diseño, solo se usa HTTPS para la comunicación con el cliente, no para la comunicación entre contenedores de la misma aplicación web. Solo
WebFrontEndnecesita HTTPS y el código de los ejemplos supone que ha desactivado esa casilla. En general, los certificados de desarrollador de .NET usados por Visual Studio solo se admiten para las solicitudes externas a contenedor, no para las solicitudes de contenedor a contenedor.
Agregue compatibilidad con Azure Cache for Redis. Agregue el paquete NuGet
Microsoft.Extensions.Caching.StackExchangeRedis(no elStackExchange.Redis). En Program.cs, agregue las líneas siguientes, justo antes devar app = builder.Build():builder.Services.AddStackExchangeRedisCache(options => { options.Configuration = "redis:6379"; // redis is the container name of the redis service. 6379 is the default port options.InstanceName = "SampleInstance"; });Agregue directivas de uso en
Program.csparaMicrosoft.Extensions.Caching.DistributedyMicrosoft.Extensions.Caching.StackExchangeRedis.using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Caching.StackExchangeRedis;En el proyecto de Web API, elimine los archivos existentes
WeatherForecast.csy Controllers/WeatherForecastController.cs, y agregue un archivo en Controladores, CounterController.cs, con el siguiente contenido:using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Caching.Distributed; using StackExchange.Redis; namespace WebApi.Controllers { [ApiController] [Route("[controller]")] public class CounterController : ControllerBase { private readonly ILogger<CounterController> _logger; private readonly IDistributedCache _cache; public CounterController(ILogger<CounterController> logger, IDistributedCache cache) { _logger = logger; _cache = cache; } [HttpGet(Name = "GetCounter")] public string Get() { string key = "Counter"; string? result = null; try { var counterStr = _cache.GetString(key); if (int.TryParse(counterStr, out int counter)) { counter++; } else { counter = 0; } result = counter.ToString(); _cache.SetString(key, result); } catch(RedisConnectionException) { result = "Redis cache is not found."; } return result; } } }El servicio incrementa un contador cada vez que se accede a la página y almacena el contador en la memoria caché.
Adición de código para llamar a la API web
En el proyecto
WebFrontEnd, abra el archivo Index.cshtml.cs y reemplace el métodoOnGetpor el código siguiente.public async Task OnGet() { // Call *mywebapi*, and display its response in the page using (var client = new System.Net.Http.HttpClient()) { var request = new System.Net.Http.HttpRequestMessage(); // A delay is a quick and dirty way to work around the fact that // the mywebapi service might not be immediately ready on startup. // See the text for some ideas on how you can improve this. // Uncomment if not using healthcheck (Visual Studio 17.13 or later) // await System.Threading.Tasks.Task.Delay(10000); // mywebapi is the service name, as listed in docker-compose.yml. // Docker Compose creates a default network with the services // listed in docker-compose.yml exposed as host names. // The port 8080 is exposed in the WebAPI Dockerfile. // If your WebAPI is exposed on port 80 (the default for HTTP, used // with earlier versions of the generated Dockerfile), change // or delete the port number here. request.RequestUri = new Uri("http://mywebapi:8080/Counter"); var response = await client.SendAsync(request); string counter = await response.Content.ReadAsStringAsync(); ViewData["Message"] = $"Counter value from cache :{counter}"; } }Nota
En el código del mundo real, no se debe desechar
HttpClientdespués de cada solicitud. Para conocer los procedimientos recomendados, consulte Usar HttpClientFactory para implementar solicitudes HTTP resistentes.El URI especificado hace referencia a un nombre de servicio definido en el archivo docker-compose.yml. Docker Compose configura una red predeterminada para la comunicación entre contenedores mediante los nombres de servicio enumerados como hosts.
El código que se muestra aquí funciona con .NET 8 y versiones posteriores, que configura una cuenta de usuario en el Dockerfile sin privilegios de administrador y expone el puerto 8080 porque el puerto predeterminado HTTP 80 no es accesible sin privilegios elevados.
En el archivo
Index.cshtml, agregue una línea para mostrarViewData["Message"]para que el archivo tenga un aspecto similar al código siguiente:@page @model IndexModel @{ ViewData["Title"] = "Home page"; } <div class="text-center"> <h1 class="display-4">Welcome</h1> <p>Learn about <a href="/aspnet/core">building Web apps with ASP.NET Core</a>.</p> <p>@ViewData["Message"]</p> </div>Este código muestra el valor del contador devuelto desde el proyecto de API web. Se incrementa cada vez que el usuario accede o actualiza la página.
Adición de compatibilidad con Docker Compose
En el proyecto
WebFrontEnd, seleccione Agregar > Compatibilidad con el orquestador de contenedores. Aparece el cuadro de diálogo Opciones de soporte de Docker.Seleccione Docker Compose.
Visual Studio 17.12 y versiones posteriores Elija las opciones de scaffolding para el proyecto WebFrontEnd.
Visual Studio 17.11 y versiones anteriores Elegir el sistema operativo de destino, por ejemplo, Linux.
Visual Studio crea un archivo docker-compose.yml y un archivo
.dockerignoreen el nodo docker-compose de la solución, y ese proyecto se muestra en negrita, lo que indica que es el proyecto de inicio.
El docker-compose.yml aparece de la siguiente manera:
services: webfrontend: image: ${DOCKER_REGISTRY-}webfrontend build: context: . dockerfile: WebFrontEnd/DockerfileEl archivo
.dockerignorecontiene tipos de archivo y extensiones que no quiere que Docker incluya en el contenedor. Estos archivos suelen estar asociados con el entorno de desarrollo y el control de código fuente, no forman parte de la aplicación o el servicio que está desarrollando.Consulte la sección Container Tools del panel de salida para detalles de los comandos que se ejecutan. Puede ver que la herramienta de línea de comandos
docker-composese usa para configurar y crear los contenedores en tiempo de ejecución.En el proyecto de API web, vuelva a hacer clic con el botón derecho en el nodo del proyecto y seleccione Agregar>Compatibilidad con el orquestador de contenedores. Elija docker Composey, a continuación, seleccione el mismo sistema operativo de destino.
Nota
En este paso, Visual Studio ofrecerá crear un Dockerfile. Si lo hace en un proyecto que ya tiene compatibilidad con Docker, se le pedirá si desea sobrescribir el Dockerfile existente. Si ha realizado cambios en el Dockerfile que desea conservar, elija no.
Visual Studio realiza algunos cambios en el archivo
docker-composeYML. Ahora se incluyen ambos servicios.services: webfrontend: image: ${DOCKER_REGISTRY-}webfrontend build: context: . dockerfile: WebFrontEnd/Dockerfile mywebapi: image: ${DOCKER_REGISTRY-}mywebapi build: context: . dockerfile: MyWebAPI/DockerfileAgregue la memoria caché al archivo
docker-compose.yml:redis: image: redisAsegúrese de que la sangría está en el mismo nivel que los otros dos servicios.
(Visual Studio 17.13 o posterior) Los servicios dependientes muestran un problema común. La solicitud HTTP en la página principal del front-end podría ejecutarse inmediatamente en el inicio de la aplicación, antes de que el servicio
mywebapiesté listo para recibir solicitudes web. Si usa Visual Studio 17.13 o posterior, puede usar las características de Docker Composedepends_onyhealthchecken docker-compose.yml para que los proyectos se inicien en la secuencia correcta y que estén listos para atender solicitudes cuando sea necesario. Consulte Docker Compose: orden de inicio.services: webfrontend: image: ${DOCKER_REGISTRY-}webfrontend depends_on: mywebapi: condition: service_healthy build: context: . dockerfile: WebFrontEnd/Dockerfile mywebapi: image: ${DOCKER_REGISTRY-}mywebapi depends_on: redis: condition: service_started healthcheck: test: curl --fail http://mywebapi:8080/Counter || exit 1 interval: 20s timeout: 20s retries: 5 build: context: . dockerfile: MyWebAPI/Dockerfile redis: image: redisEn este ejemplo, la comprobación de estado usa
curlpara comprobar que el servicio está listo para procesar las solicitudes. Si la imagen que usa no tienecurlinstalado, agregue líneas a la fasebasedel MyWebAPI Dockerfile para instalarlo. Este paso requiere privilegios elevados, pero puede restaurar los privilegios de usuario normales después de instalarlos como se muestra aquí (para las imágenes de Debian usadas en este ejemplo):USER root RUN apt-get update && apt-get install -y curl USER $APP_UIDNota
Si usa una distribución de Linux, como Alpine, que no admite
apt-get, pruebeRUN apk --no-cache add curlen su lugar.Estas características de Docker Compose requieren una configuración de propiedad en el archivo de proyecto de Docker Compose (
.dcproj). Establezca la propiedadDependencyAwareStarten true:<PropertyGroup> <!-- existing properties --> <DependencyAwareStart>true</DependencyAwareStart> </PropertyGroup>Esta propiedad activa una forma diferente de iniciar los contenedores para la depuración que admite las características de dependencia del servicio.
Con estos cambios, el servicio
webfrontendno se iniciará hasta quemywebapise inicie y controle correctamente una solicitud web.El primer proyecto al que agrega orquestación de contenedores se configura para que se inicie cuando se ejecute o se depure. Puede configurar la acción de inicio en las Propiedades del proyecto del proyecto de Docker Compose. En el nodo del proyecto Docker Compose, haga clic con el botón derecho para abrir el menú contextual y, a continuación, elija Propiedadeso use Alt+Enter. Por ejemplo, puede cambiar la página que se carga mediante la personalización de la propiedad URL de servicio.
Presione F5. Así es como se ve cuando se inicia:
Puede supervisar los contenedores mediante la ventana Contenedores. Si no ve la ventana, use el cuadro de búsqueda, presione Ctrl+K, Ctrl+Oo presione Ctrl+Q. En Búsqueda de características, busque
containersy elija Ver>Otras ventanas>Contenedores en la lista.Expanda el nodo Contenedores de soluciones y elija el nodo para el proyecto de Docker Compose para ver los registros combinados en la pestaña Registros de esta ventana.
También puede seleccionar el nodo de un contenedor individual para ver registros, variables de entorno, el sistema de archivos y otros detalles.
Configuración de perfiles de inicio
Esta solución tiene una instancia de Azure Cache for Redis, pero no es eficiente reconstruir el contenedor de caché cada vez que inicie una sesión de depuración. Para evitar esa situación, puede configurar un par de perfiles de inicio. Cree un perfil para iniciar Azure Cache for Redis. Cree un segundo perfil para iniciar los demás servicios. El segundo perfil puede usar el contenedor de caché que ya está en ejecución. En la barra de menús, puede usar la lista desplegable junto al botón iniciar para abrir un menú con opciones de depuración. Seleccione Administrar la configuración de inicio de Docker Compose.
Aparece el cuadro de diálogo Administrar la configuración de inicio de Docker Compose. Con este cuadro de diálogo, puede controlar qué subconjunto de servicios se inicia durante una sesión de depuración, que se inicia con o sin el depurador asociado, y el servicio de inicio y la dirección URL. Consulte Administración de perfiles de inicio para Docker Compose.
Elija Nuevo para crear un nuevo perfil y asígnelo el nombre
Start Redis. A continuación, establezca el contenedor de Redis en Iniciar sin depurar, deje el otro conjunto en No iniciar y elija Guardar.
A continuación, cree otro perfil
Start My Servicesque no inicie Redis, pero inicia los otros dos servicios.
(Opcional) Cree un tercer perfil
Start Allpara iniciar todo. Puede elegir Iniciar sin depurar para Redis.Elija Iniciar Redis en la lista desplegable de la barra de herramientas principal de Visual Studio. El contenedor de Redis se compila e inicia sin depurar. Puede usar la ventana Contenedores para ver que se está ejecutando. A continuación, elija Iniciar mis servicios en la lista desplegable y presione F5 para iniciarlos. Ahora puede mantener el contenedor de caché en ejecución en muchas sesiones de depuración posteriores. Cada vez que use Iniciar mis servicios, esos servicios usan el mismo contenedor de caché.
Enhorabuena, está ejecutando una aplicación de Docker Compose con un perfil personalizado de Docker Compose.
Pasos siguientes
Examine las opciones para implementar los contenedores de en Azure. Si está listo para implementar en Azure Container Apps, consulte Implementación de una aplicación de varios contenedores en Azure Container Apps.