Condividi tramite


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 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.

Screenshot showing Create ASP.NET Core Web App project.

Non selezionare Abilita supporto Docker. Il supporto docker verrà aggiunto più avanti nel processo.

Screenshot of the Additional information screen when creating a web project. The option to Enable Docker Support is not selected.

Nota

In Visual Studio 2022 17.2 e versioni successive è invece possibile usare Funzioni di Azure per questo progetto.

Screenshot showing Create ASP.NET Core Web App project.

Non selezionare Abilita supporto Docker. Il supporto docker verrà aggiunto più avanti nel processo.

Screenshot of the Additional information screen when creating a web project. The option to Enable Docker Support is not selected.

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.

Screenshot of creating the Web API project.

  1. 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.

    Screenshot of creating the Web API project.

  2. Aggiungere il supporto per Cache Redis. Aggiungere il pacchetto Microsoft.Extensions.Caching.StackExchangeRedis NuGet (non StackExchange.Redis). In Program.cs aggiungere le righe seguenti, subito prima var 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";
       });
    
  3. Aggiungere direttive using in Program.cs per Microsoft.Extensions.Caching.Distributed e Microsoft.Extensions.Caching.StackExchangeRedis.

    using Microsoft.Extensions.Caching.Distributed;
    using Microsoft.Extensions.Caching.StackExchangeRedis;
    
  4. 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

  1. WebFrontEnd Nel progetto aprire il file Index.cshtml.cs e sostituire il OnGet 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.

  2. 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>
    
  3. (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

  1. Nel progetto scegliere Aggiungi > supporto dell'agente WebFrontEnd di orchestrazione contenitori. Viene visualizzata la finestra di dialogo Opzioni supporto Docker.

  2. Scegliere Docker Compose.

  3. Scegliere il sistema operativo di destinazione, ad esempio Linux.

    Screenshot of choosing the Target OS.

    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.

    Screenshot of Solution Explorer with docker-compose project added.

    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.

  4. 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
    
  5. 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.

    Screenshot of docker-compose project properties.

    Ecco cosa viene visualizzato all'avvio (versione di .NET Core 2.x):

    Screenshot of running web app.

    L'app Web per .NET 3.1 mostra i dati meteo in formato JSON.

  6. 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.

    Screenshot of Debug Manage Compose Settings menu item.

    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.

    Screenshot of Manage Docker Compose Launch Settings dialog box.

    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.

  7. Premere F5 per confermare il funzionamento come previsto.

Si esegue un'applicazione Docker Compose con un profilo Docker Compose personalizzato.

  1. WebFrontEnd Nel progetto aprire il file Index.cshtml.cs e sostituire il OnGet 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.

  2. 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

  1. Nel progetto scegliere Aggiungi > supporto dell'agente WebFrontEnd di orchestrazione contenitori. Viene visualizzata la finestra di dialogo Opzioni supporto Docker.

  2. Scegliere Docker Compose.

  3. Scegliere il sistema operativo di destinazione, ad esempio Linux.

    Screenshot of choosing the Target OS.

    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.

    Screenshot of Solution Explorer with docker-compose project added.

    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.

  4. 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
    
  5. Aggiungere la cache Redis al docker.compose.yml file:

    redis:
       image: redis
    

    Assicurarsi che il rientro sia allo stesso livello degli altri due servizi.

  6. 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.

    Screenshot of docker-compose project properties.

  7. Premere F5. Ecco cosa viene visualizzato all'avvio:

    Screenshot of running web app.

  8. È 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 containerse scegliere Visualizza>altri contenitori di Windows>dall'elenco.

  9. 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.

    Screenshot showing viewing the Logs tab in the Containers window.

    È 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

  1. 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.

    Screenshot of Debug Manage Compose Settings menu item.

    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.

    Screenshot of Manage Docker Compose Launch Settings dialog box.

    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.

    Screenshot showing creating the Redis profile that starts the Redis service only.

    Creare quindi un altro profilo Start My Services che non avvia Redis, ma avvia gli altri due servizi.

    Screenshot showing creating the Services profile that starts the other services.

    (Facoltativo) Creare un terzo profilo Start All per avviare tutto. È possibile scegliere Avvia senza eseguire il debug per Redis.

  2. 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.

Vedi anche

Docker Compose
Strumenti contenitore