Esercitazione: Creare un'app multi-contenitore con Docker Compose
In questa esercitazione si apprenderà come gestire più contenitori e comunicare tra di essi quando si usa Strumenti contenitore in Visual Studio. La gestione di più contenitori richiede l'orchestrazione dei contenitori e richiede un agente di orchestrazione, ad esempio Docker Compose o Service Fabric. Per queste procedure, si usa Docker Compose. Docker Compose è ideale per il debug e il test locali nel corso del ciclo di sviluppo.
L'esempio completato creato in questa esercitazione è disponibile in GitHub all'indirizzo https://github.com/MicrosoftDocs/vs-tutorial-samples nella cartella docker/ComposeSample.
Prerequisiti
- Docker Desktop
- Visual Studio 2019 con il carico di lavoro Sviluppo Web, Strumenti di Azure e/o Sviluppo multipiattaforma .NET installato
- Docker Desktop
- Visual Studio 2022 con il carico di lavoro Sviluppo Web, Strumenti di Azure e/o Sviluppo multipiattaforma .NET installato. Questa installazione include gli strumenti di sviluppo .NET 8.
Creare un progetto di applicazione Web
In Visual Studio creare un progetto di ASP.NET Core Web App , denominato WebFrontEnd
, per creare un'applicazione Web con pagine Razor.
Non selezionare Abilita supporto Docker. Il supporto docker verrà aggiunto più avanti nel processo.
Nota
In Visual Studio 2022 17.2 e versioni successive è invece possibile usare Funzioni di Azure per questo progetto.
Non selezionare Abilita supporto Docker. Il supporto docker verrà aggiunto più avanti nel processo.
Creare un progetto API Web
Aggiungere un progetto alla stessa soluzione e chiamarlo MyWebAPI. Selezionare API come tipo di progetto e deselezionare la casella di controllo Configura per HTTPS. In questa progettazione si usa SSL solo per la comunicazione con il client, non per la comunicazione tra contenitori nella stessa applicazione Web. Richiede solo WebFrontEnd
HTTPS e il codice negli esempi presuppone che la casella di controllo sia stata deselezionata. In generale, i certificati per sviluppatori .NET usati da Visual Studio sono supportati solo per le richieste da esterno a contenitore, non per le richieste da contenitore a contenitore.
Aggiungere un progetto alla stessa soluzione e chiamarlo WebAPI. Selezionare API come tipo di progetto e deselezionare la casella di controllo Configura per HTTPS. In questa progettazione si usa SSL solo per la comunicazione con il client, non per la comunicazione tra contenitori nella stessa applicazione Web. Richiede solo
WebFrontEnd
HTTPS e il codice negli esempi presuppone che la casella di controllo sia stata deselezionata. In generale, i certificati per sviluppatori .NET usati da Visual Studio sono supportati solo per le richieste da esterno a contenitore, non per le richieste da contenitore a contenitore.Aggiungere il supporto per Cache Redis. Aggiungere il pacchetto
Microsoft.Extensions.Caching.StackExchangeRedis
NuGet (nonStackExchange.Redis
). In Program.cs aggiungere le righe seguenti, subito primavar app = builder.Build()
di :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"; });
Aggiungere direttive using in Program.cs per
Microsoft.Extensions.Caching.Distributed
eMicrosoft.Extensions.Caching.StackExchangeRedis
.using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Caching.StackExchangeRedis;
Nel progetto API Web eliminare i controller WeatherForecast.cs e Controllers/WeatherForecastController.cs e aggiungere un file in Controllers, CounterController.cs, con il contenuto seguente:
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; } } }
Il servizio incrementa un contatore ogni volta che si accede alla pagina e archivia il contatore nella cache Redis.
Aggiungere codice per chiamare l'API Web
WebFrontEnd
Nel progetto aprire il file Index.cshtml.cs e sostituire ilOnGet
metodo con il codice seguente.public async Task OnGet() { ViewData["Message"] = "Hello from webfrontend"; using (var client = new System.Net.Http.HttpClient()) { // Call *mywebapi*, and display its response in the page var request = new System.Net.Http.HttpRequestMessage(); request.RequestUri = new Uri("http://mywebapi/WeatherForecast"); // request.RequestUri = new Uri("http://mywebapi/api/values/1"); // For ASP.NET 2.x, comment out previous line and uncomment this line. var response = await client.SendAsync(request); ViewData["Message"] += " and " + await response.Content.ReadAsStringAsync(); } }
Nota
Nel codice reale non è consigliabile eliminare
HttpClient
dopo ogni richiesta. Per le procedure consigliate, vedere Usare HttpClientFactory per implementare richieste HTTP resilienti.Nel file index.cshtml aggiungere una riga per visualizzare
ViewData["Message"]
in modo che il file abbia un aspetto simile al codice seguente:@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>
(solo ASP.NET 2.x) Nel progetto API Web aggiungere ora il codice al controller Valori per personalizzare il messaggio restituito dall'API per la chiamata aggiunta da webfrontend.
// GET api/values/5 [HttpGet("{id}")] public ActionResult<string> Get(int id) { return "webapi (with value " + id + ")"; }
Nota
In .NET Core 3.1 e versioni successive è possibile usare l'API WeatherForecast fornita anziché questo codice aggiuntivo. Tuttavia, è necessario impostare come commento la chiamata a UseHttpsRedirection nel progetto API Web perché il codice usa HTTP per effettuare la chiamata anziché HTTPS.
//app.UseHttpsRedirection();
Aggiungere il supporto di Docker Compose
Nel progetto scegliere Aggiungi > supporto dell'agente
WebFrontEnd
di orchestrazione contenitori. Viene visualizzata la finestra di dialogo Opzioni supporto Docker.Scegliere Docker Compose.
Scegliere il sistema operativo di destinazione, ad esempio Linux.
Visual Studio crea un file docker-compose.yml e un file con estensione dockerignore nel nodo docker-compose nella soluzione e tale progetto mostra il carattere grassetto, che mostra che è il progetto di avvio.
Il file docker-compose.yml viene visualizzato come segue:
version: '3.4' services: webfrontend: image: ${DOCKER_REGISTRY-}webfrontend build: context: . dockerfile: WebFrontEnd/Dockerfile
L'oggetto
version
specificato nella prima riga è la versione del file Docker Compose. In genere non è consigliabile modificarlo, perché viene usato dagli strumenti per comprendere come interpretare il file.Il file con estensione dockerignore contiene i tipi di file e le estensioni che non si desidera includere Docker nel contenitore. Questi file sono in genere associati all'ambiente di sviluppo e al controllo del codice sorgente, non a parte dell'app o del servizio in fase di sviluppo.
Per informazioni dettagliate sui comandi in esecuzione, vedere la sezione Strumenti contenitore del riquadro di output. È possibile vedere che lo strumento da riga di comando docker-compose viene usato per configurare e creare i contenitori di runtime.
Nel progetto API Web fare di nuovo clic con il pulsante destro del mouse sul nodo del progetto e scegliere Aggiungi>supporto dell'agente di orchestrazione contenitori. Scegliere Docker Compose e quindi selezionare lo stesso sistema operativo di destinazione.
Nota
In questo passaggio, Visual Studio offrirà di creare un Dockerfile. Se si esegue questa operazione in un progetto che dispone già del supporto docker, viene richiesto se si vuole sovrascrivere il Dockerfile esistente. Se sono state apportate modifiche nel Dockerfile da mantenere, scegliere no.
Visual Studio apporta alcune modifiche al file docker compose YML. Ora sono inclusi entrambi i servizi.
version: '3.4' services: webfrontend: image: ${DOCKER_REGISTRY-}webfrontend build: context: . dockerfile: WebFrontEnd/Dockerfile mywebapi: image: ${DOCKER_REGISTRY-}mywebapi build: context: . dockerfile: MyWebAPI/Dockerfile
Il primo progetto a cui si aggiunge l'orchestrazione dei contenitori è configurato per l'avvio quando si esegue o si esegue il debug. È possibile configurare l'azione di avvio in Proprietà progetto per il progetto docker-compose. Nel nodo del progetto docker-compose fare clic con il pulsante destro del mouse per aprire il menu di scelta rapida, quindi scegliere Proprietà oppure usare ALT+INVIO. Lo screenshot seguente mostra le proprietà desiderate per la soluzione usata qui. Ad esempio, è possibile modificare la pagina caricata personalizzando la proprietà URL del servizio.
Ecco cosa viene visualizzato all'avvio (versione di .NET Core 2.x):
L'app Web per .NET 3.1 mostra i dati meteo in formato JSON.
Si supponga ora di essere interessati solo a avere il debugger collegato a WebFrontEnd, non al progetto API Web. Dalla barra dei menu è possibile usare l'elenco a discesa accanto al pulsante Start per visualizzare un menu di opzioni di debug; scegliere Manage Docker Compose Launch (Gestisci avvio Docker Compose) Impostazioni.
Viene visualizzata la finestra di dialogo Gestisci avvio di Docker Compose Impostazioni. Con questa finestra di dialogo è possibile controllare il subset di servizi avviato durante una sessione di debug, che vengono avviate con o senza il debugger collegato e il servizio di avvio e l'URL. Vedere Avviare un subset di servizi Compose.
Scegliere Nuovo per creare un nuovo profilo e denominarlo
Debug WebFrontEnd only
. Impostare quindi il progetto API Web su Avvia senza eseguire il debug, lasciare il progetto WebFrontEnd impostato per iniziare con il debug e scegliere Salva.La nuova configurazione viene scelta come predefinita per il successivo F5.
Premere F5 per confermare il funzionamento come previsto.
Si esegue un'applicazione Docker Compose con un profilo Docker Compose personalizzato.
WebFrontEnd
Nel progetto aprire il file Index.cshtml.cs e sostituire ilOnGet
metodo con il codice seguente.public async Task OnGet() { using (var client = new System.Net.Http.HttpClient()) { // Call *mywebapi*, and display its response in the page var request = new System.Net.Http.HttpRequestMessage(); // webapi is the container name request.RequestUri = new Uri("http://webapi/Counter"); var response = await client.SendAsync(request); string counter = await response.Content.ReadAsStringAsync(); ViewData["Message"] = $"Counter value from cache :{counter}"; } }
Nota
Nel codice reale non è consigliabile eliminare
HttpClient
dopo ogni richiesta. Per le procedure consigliate, vedere Usare HttpClientFactory per implementare richieste HTTP resilienti.Nel file index.cshtml aggiungere una riga per visualizzare
ViewData["Message"]
in modo che il file abbia un aspetto simile al codice seguente:@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>
Questo codice visualizza il valore del contatore restituito dal progetto API Web.
Aggiungere il supporto di Docker Compose
Nel progetto scegliere Aggiungi > supporto dell'agente
WebFrontEnd
di orchestrazione contenitori. Viene visualizzata la finestra di dialogo Opzioni supporto Docker.Scegliere Docker Compose.
Scegliere il sistema operativo di destinazione, ad esempio Linux.
Visual Studio crea un file docker-compose.yml e un file con estensione dockerignore nel nodo docker-compose nella soluzione e tale progetto mostra il carattere grassetto, che mostra che è il progetto di avvio.
Il file docker-compose.yml viene visualizzato come segue:
version: '3.4' services: webfrontend: image: ${DOCKER_REGISTRY-}webfrontend build: context: . dockerfile: WebFrontEnd/Dockerfile
L'oggetto
version
specificato nella prima riga è la versione del file Docker Compose. In genere non è consigliabile modificarlo, perché viene usato dagli strumenti per comprendere come interpretare il file.Il file con estensione dockerignore contiene i tipi di file e le estensioni che non si desidera includere Docker nel contenitore. Questi file sono in genere associati all'ambiente di sviluppo e al controllo del codice sorgente, non a parte dell'app o del servizio in fase di sviluppo.
Per informazioni dettagliate sui comandi in esecuzione, vedere la sezione Strumenti contenitore del riquadro di output. È possibile vedere che lo strumento da riga di comando docker-compose viene usato per configurare e creare i contenitori di runtime.
Nel progetto API Web fare di nuovo clic con il pulsante destro del mouse sul nodo del progetto e scegliere Aggiungi>supporto dell'agente di orchestrazione contenitori. Scegliere Docker Compose e quindi selezionare lo stesso sistema operativo di destinazione.
Nota
In questo passaggio, Visual Studio offrirà di creare un Dockerfile. Se si esegue questa operazione in un progetto che dispone già del supporto docker, viene richiesto se si vuole sovrascrivere il Dockerfile esistente. Se sono state apportate modifiche nel Dockerfile da mantenere, scegliere no.
Visual Studio apporta alcune modifiche al file docker compose YML. Ora sono inclusi entrambi i servizi.
version: '3.4' services: webfrontend: image: ${DOCKER_REGISTRY-}webfrontend build: context: . dockerfile: WebFrontEnd/Dockerfile mywebapi: image: ${DOCKER_REGISTRY-}mywebapi build: context: . dockerfile: MyWebAPI/Dockerfile
Aggiungere la cache Redis al
docker.compose.yml
file:redis: image: redis
Assicurarsi che il rientro sia allo stesso livello degli altri due servizi.
Il primo progetto a cui si aggiunge l'orchestrazione dei contenitori è configurato per l'avvio quando si esegue o si esegue il debug. È possibile configurare l'azione di avvio in Proprietà progetto per il progetto docker-compose. Nel nodo del progetto docker-compose fare clic con il pulsante destro del mouse per aprire il menu di scelta rapida, quindi scegliere Proprietà oppure premere ALT+INVIO. Ad esempio, è possibile modificare la pagina caricata personalizzando la proprietà URL del servizio.
Premere F5. Ecco cosa viene visualizzato all'avvio:
È possibile monitorare i contenitori usando la finestra Contenitori . Se la finestra non viene visualizzata, usare la casella di ricerca, premere CTRL+K, CTRL+O o premere CTRL+Q. In Ricerca funzionalità cercare
containers
e scegliere Visualizza>altri contenitori di Windows>dall'elenco.Espandere il nodo Contenitori di soluzioni e scegliere il nodo per il progetto Docker Compose per visualizzare i log combinati nella scheda Log di questa finestra.
È anche possibile selezionare il nodo per un singolo contenitore per visualizzare log, variabili di ambiente, file system e altri dettagli.
Configurare i profili di avvio
Questa soluzione ha una cache Redis, ma non è efficiente ricompilare il contenitore cache Redis ogni volta che si avvia una sessione di debug. Per evitare questa situazione, è possibile configurare un paio di profili di avvio. Creare un profilo per avviare la cache Redis. Creare un secondo profilo per avviare gli altri servizi. Il secondo profilo può usare il contenitore cache Redis già in esecuzione. Dalla barra dei menu è possibile usare l'elenco a discesa accanto al pulsante Start per aprire un menu con le opzioni di debug. Selezionare Manage Docker Compose Launch (Gestisci avvio Docker Compose) Impostazioni.
Viene visualizzata la finestra di dialogo Gestisci avvio di Docker Compose Impostazioni. Con questa finestra di dialogo è possibile controllare il subset di servizi avviato durante una sessione di debug, che vengono avviate con o senza il debugger collegato e il servizio di avvio e l'URL. Vedere Avviare un subset di servizi Compose.
Scegliere Nuovo per creare un nuovo profilo e denominarlo
Start Redis
. Impostare quindi il contenitore Redis su Avvia senza eseguire il debug, lasciare l'altro impostato su Non avviare e scegliere Salva.Creare quindi un altro profilo
Start My Services
che non avvia Redis, ma avvia gli altri due servizi.(Facoltativo) Creare un terzo profilo
Start All
per avviare tutto. È possibile scegliere Avvia senza eseguire il debug per Redis.Scegliere Avvia Redis dall'elenco a discesa sulla barra degli strumenti principale di Visual Studio, premere F5. Il contenitore Redis compila e avvia. È possibile usare la finestra Contenitori per verificare che sia in esecuzione. Scegliere quindi Avvia i miei servizi dall'elenco a discesa e premere F5 per avviarli. È ora possibile mantenere in esecuzione il contenitore cache Redis in molte sessioni di debug successive. Ogni volta che si usano Start My Services, questi servizi usano lo stesso contenitore di cache Redis.
Si esegue un'applicazione Docker Compose con un profilo Docker Compose personalizzato.
Passaggi successivi
Esaminare le opzioni per la distribuzione dei contenitori in Azure.