Dela via


Självstudie: Skapa en app med flera containrar med Docker Compose

I den här självstudien får du lära dig hur du hanterar mer än en container och kommunicerar mellan dem när du använder Container Tools i Visual Studio. För att hantera flera containrar krävs containerorkestrering och kräver en orkestrerare som Docker Compose eller Service Fabric. För dessa procedurer använder du Docker Compose. Docker Compose är perfekt för lokal felsökning och testning under utvecklingscykeln.

Det färdiga exemplet som du skapar i den här självstudien finns på GitHub på https://github.com/MicrosoftDocs/vs-tutorial-samples i mappen docker/ComposeSample.

Förutsättningar

  • Docker Desktop
  • Visual Studio 2019 med Web Development, Azure Tools arbetsbelastning och/eller .NET-plattformsoberoende utveckling arbetsbelastning installerad
  • Docker Desktop
  • Visual Studio 2022 med arbetsprogrammet Web Development, Azure Tools och/eller .NET-plattformsoberoende utveckling arbetsprogram installerat. Den här installationen innehåller .NET 8-utvecklingsverktygen.

Skapa ett webbprogramprojekt

I Visual Studio skapar du ett ASP.NET Core Web App-projekt med namnet WebFrontEndför att skapa ett webbprogram med Razor-sidor.

Skärmbild som visar projektet Skapa ASP.NET Core Web App.

Välj inte Aktivera Docker-stödet. Du lägger till Docker-stöd senare i processen.

Skärmbild av skärmen Ytterligare information när du skapar ett webbprojekt. Alternativet Aktivera Docker-support är inte markerat.

Välj inte Aktivera Docker-stödet. Du lägger till Docker-stöd senare i processen.

Skärmbild av skärmen Ytterligare information när du skapar ett webbprojekt. Alternativet Aktivera Docker-support är inte markerat.

Skapa ett webb-API-projekt

Lägg till ett projekt i samma lösning och anropa det MyWebAPI. Välj API som projekttyp och avmarkera kryssrutan för Konfigurera för HTTPS-. I den här designen använder vi bara SSL för kommunikation med klienten, inte för kommunikation mellan containrar i samma webbprogram. Endast WebFrontEnd behöver HTTPS och koden i exemplen förutsätter att du har avmarkerat kryssrutan. I allmänhet stöds .NET-utvecklarcertifikaten som används av Visual Studio endast för begäranden från externa till container, inte för begäranden från container till container.

Skärmbild av hur du skapar webb-API-projektet.

  1. Lägg till ett projekt i samma lösning och anropa det MyWebAPI. Välj API som projekttyp och avmarkera kryssrutan för Konfigurera för HTTPS-.

    Notera

    I den här designen använder vi bara HTTPS för kommunikation med klienten, inte för kommunikation mellan containrar i samma webbprogram. Endast WebFrontEnd behöver HTTPS och koden i exemplen förutsätter att du har avmarkerat kryssrutan. I allmänhet stöds .NET-utvecklarcertifikaten som används av Visual Studio endast för begäranden från externa till container, inte för begäranden från container till container.

    Skärmbild av hur du skapar webb-API-projektet.

  2. Lägg till stöd för Azure Cache for Redis. Lägg till NuGet-paketet Microsoft.Extensions.Caching.StackExchangeRedis (inte StackExchange.Redis). I Program.cslägger du till följande rader strax före var 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";
       });
    
  3. Lägg till med hjälp av direktiv i Program.cs för Microsoft.Extensions.Caching.Distributed och Microsoft.Extensions.Caching.StackExchangeRedis.

    using Microsoft.Extensions.Caching.Distributed;
    using Microsoft.Extensions.Caching.StackExchangeRedis;
    
  4. I webb-API-projektet tar du bort befintliga WeatherForecast.cs och Controllers/WeatherForecastController.csoch lägger till en fil under Kontrollanter CounterController.csmed följande innehåll:

    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;
            }
        }
    }
    

    Tjänsten ökar en räknare varje gång sidan används och lagrar räknaren i cacheminnet.

Lägga till kod för att anropa webb-API:et

  1. I WebFrontEnd-projektet öppnar du filen Index.cshtml.cs och ersätter metoden OnGet med följande kod.

     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();
        }
     }
    

    Notera

    I verklig kod bör du inte ta bort HttpClient efter varje begäran. Metodtips finns i Använda HttpClientFactory för att implementera motståndskraftiga HTTP-begäranden.

  2. I filen Index.cshtml lägger du till en rad för att visa ViewData["Message"] så att filen ser ut som följande kod:

    @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. (endast ASP.NET 2.x) Lägg nu till kod i kontrollanten Värden i webb-API-projektet för att anpassa meddelandet som returneras av API:et för det anrop som du lade till från webfrontend.

    // GET api/values/5
    [HttpGet("{id}")]
    public ActionResult<string> Get(int id)
    {
       return "webapi (with value " + id + ")";
    }
    

    Notera

    I .NET Core 3.1 och senare kan du använda det angivna WeatherForecast-API:et i stället för den här extra koden. Du måste dock kommentera ut anropet till UseHttpsRedirection i webb-API-projektet eftersom koden använder HTTP för att göra anropet i stället för HTTPS.

          //app.UseHttpsRedirection();
    

Lägg till Stöd för Docker Compose

  1. I projektet WebFrontEnd, välj Lägg till stöd för > containerorkestrerare. Dialogrutan Alternativ för Docker-support visas.

  2. Välj Docker Compose.

  3. Välj ditt måloperativsystem, till exempel Linux.

    Skärmbild av val av måloperativsystem.

    Visual Studio skapar en docker-compose.yml-fil och en .dockerignore fil i docker-compose nod i lösningen, och det projektet visas i fetstil, vilket visar att det är startprojektet.

    Skärmbild av Solution Explorer med Docker Compose-projektet tillagt.

    docker-compose.yml visas på följande sätt:

     services:
       webfrontend:
         image: ${DOCKER_REGISTRY-}webfrontend
         build:
           context: .
           dockerfile: WebFrontEnd/Dockerfile
    

    Den version som anges på den första raden är Docker Compose-filversion. Du bör normalt inte ändra den, eftersom den används av verktygen för att förstå hur du tolkar filen.

    Filen .dockerignore innehåller filtyper och tillägg som du inte vill att Docker ska inkludera i containern. Dessa filer är vanligtvis associerade med utvecklingsmiljön och källkontrollen, inte en del av den app eller tjänst som du utvecklar.

    Titta på avsnittet Container Tools i utdatafönstret för mer information om de kommandon som körs. Du kan se kommandoradsverktyget docker-compose används för att konfigurera och skapa körningscontainrar.

  4. Högerklicka igen på projektnoden i webb-API-projektet och välj Lägg till>Container Orchestrator-stöd. Välj Docker Composeoch välj sedan samma måloperativsystem.

    Notera

    I det här steget erbjuder Visual Studio att skapa en Dockerfile. Om du gör detta i ett projekt som redan har Docker-stöd, tillfrågas du om du vill skriva över den befintliga Dockerfile. Om du har gjort ändringar i din Dockerfile som du vill behålla väljer du nej.

    Visual Studio gör vissa ändringar i Docker Compose YML-filen. Nu ingår båda tjänsterna.

    services:
      webfrontend:
        image: ${DOCKER_REGISTRY-}webfrontend
        build:
          context: .
          dockerfile: WebFrontEnd/Dockerfile
    
      mywebapi:
        image: ${DOCKER_REGISTRY-}mywebapi
        build:
          context: .
          dockerfile: MyWebAPI/Dockerfile
    
  5. Det första projektet som du lägger till containerorkestrering i konfigureras för att startas när du kör eller felsöker. Du kan konfigurera startåtgärden i Project Properties för Docker Compose-projektet. På projektnoden Docker Compose högerklickar du för att öppna snabbmenyn och väljer sedan Egenskapereller använder Alt+Retur. Följande skärmbild visar de egenskaper som du vill använda för lösningen som används här. Till exempel kan du ändra sidan som läses in genom att anpassa Service-URL-egenskapen .

    Skärmbild av Docker Compose-projektegenskaper.

    Här är vad du ser när du startar (.NET Core 2.x-versionen):

    Skärmbild av webbappen som är igång.

    Webbappen för .NET 3.1 visar väderdata i JSON-format.

  6. Anta nu att du bara är intresserad av att ha felsökningsprogrammet kopplat till WebFrontEnd, inte webb-API-projektet. Från menyraden kan du använda listrutan bredvid startknappen för att visa en meny med felsökningsalternativ. välj Hantera Startinställningar för Docker Compose.

    Skärmbild av menyalternativet Hantera skrivinställningar för felsökning.

    Dialogrutan Hantera Startinställningar för Docker Compose visas. Med den här dialogrutan kan du styra vilken delmängd av tjänster som startas under en felsökningssession, som startas med eller utan felsökningsprogrammet kopplat, samt starttjänsten och URL:en. Se Starta en delmängd av Compose-tjänster.

    Skärmbild av dialogrutan Hantera Startinställningar för Docker Compose.

    Välj Ny för att skapa en ny profil och ge den namnet Debug WebFrontEnd only. Ställ sedan in webb-API-projektet på Starta utan att felsöka, lämna Projektet WebFrontEnd inställt på att börja med felsökning och välj Spara.

    Den nya konfigurationen väljs som standard för nästa F5.

  7. Tryck på F5 för att bekräfta att det fungerar som förväntat.

Grattis, du kör ett Docker Compose-program med en anpassad Docker Compose-profil.

  1. I WebFrontEnd-projektet öppnar du filen Index.cshtml.cs och ersätter metoden OnGet med följande kod.

    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}";
       }
    }
    

    Notera

    I verklig kod bör du inte ta bort HttpClient efter varje begäran. Metodtips finns i Använda HttpClientFactory för att implementera motståndskraftiga HTTP-begäranden.

    Den angivna URI:n refererar till ett tjänstnamn som definierats i filen docker-compose.yml. Docker Compose konfigurerar ett standardnätverk för kommunikation mellan containrar med hjälp av de tjänstnamn som anges som värdar.

    Koden som visas här fungerar med .NET 8 och senare, som konfigurerar ett användarkonto i Dockerfile utan administratörsbehörighet och exponerar port 8080 eftersom HTTP-standardporten 80 inte är tillgänglig utan förhöjd behörighet.

  2. I filen Index.cshtml lägger du till en rad för att visa ViewData["Message"] så att filen ser ut som följande kod:

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

    Den här koden visar värdet för räknaren som returneras från webb-API-projektet. Den ökar varje gång användaren kommer åt eller uppdaterar sidan.

Lägg till Stöd för Docker Compose

  1. I projektet WebFrontEnd, välj Lägg till stöd för > containerorkestrerare. Dialogrutan Alternativ för Docker-support visas.

  2. Välj Docker Compose.

  3. Visual Studio 17.12 och senare Välj scaffolding-alternativen för WebFrontEnd-projektet.

    Skärmbild som visar dialogrutan Alternativ för containermallar för WebFrontEnd-projektet.

    Visual Studio 17.11 och tidigare Välj ditt måloperativsystem, till exempel Linux.

    Skärmbild av val av måloperativsystem.

    Visual Studio skapar en docker-compose.yml-fil och en .dockerignore fil i docker-compose nod i lösningen, och det projektet visas i fetstil, vilket visar att det är startprojektet.

    Skärmbild av Solution Explorer med Docker Compose-projektet tillagt.

    docker-compose.yml visas på följande sätt:

     services:
       webfrontend:
         image: ${DOCKER_REGISTRY-}webfrontend
         build:
           context: .
           dockerfile: WebFrontEnd/Dockerfile
    

    Filen .dockerignore innehåller filtyper och tillägg som du inte vill att Docker ska inkludera i containern. Dessa filer är vanligtvis associerade med utvecklingsmiljön och källkontrollen, inte en del av den app eller tjänst som du utvecklar.

    Titta på avsnittet Container Tools i utdatafönstret för mer information om de kommandon som körs. Du kan se kommandoradsverktyget docker-compose används för att konfigurera och skapa körningscontainrar.

  4. Högerklicka igen på projektnoden i webb-API-projektet och välj Lägg till>Container Orchestrator-stöd. Välj Docker Composeoch välj sedan samma måloperativsystem.

    Notera

    I det här steget erbjuder Visual Studio att skapa en Dockerfile. Om du gör detta i ett projekt som redan har Docker-stöd, tillfrågas du om du vill skriva över den befintliga Dockerfile. Om du har gjort ändringar i din Dockerfile som du vill behålla väljer du nej.

    Visual Studio gör vissa ändringar i din docker-compose YML-fil. Nu ingår båda tjänsterna.

    services:
      webfrontend:
        image: ${DOCKER_REGISTRY-}webfrontend
        build:
          context: .
          dockerfile: WebFrontEnd/Dockerfile
    
      mywebapi:
        image: ${DOCKER_REGISTRY-}mywebapi
        build:
          context: .
          dockerfile: MyWebAPI/Dockerfile
    
  5. Lägg till cachen i docker-compose.yml-filen:

    redis:
       image: redis
    

    Kontrollera att indenteringen är på samma nivå som de andra två tjänsterna.

  6. (Visual Studio 17.13 eller senare) Beroendetjänster påvisar ett vanligt problem. HTTP-begäran i klientdelens huvudsida kan köras omedelbart vid programstart, innan mywebapi-tjänsten är redo att ta emot webbbegäranden. Om du använder Visual Studio 17.13 eller senare kan du använda Docker Compose-funktionerna depends_on och healthcheck i docker-compose.yml för att få projekten att starta i rätt ordning och låta dem vara redo att hantera begäranden vid behov. Se Docker Compose – Startordning.

    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/ || exit 1
            interval: 20s
            timeout: 20s
            retries: 5
         build:
            context: .
              dockerfile: MyWebAPI/Dockerfile
    
      redis:
         image: redis
    

    I det här exemplet använder hälsokontrollen curl för att verifiera att tjänsten är redo att bearbeta begäranden. Om avbildningen du använder inte har curl installerat lägger du till rader i base-fasen i MyWebAPI Dockerfile för att installera den. Det här steget kräver utökade privilegier, men du kan återställa de normala användarbehörigheterna efter att du har installerat det som du ser här (för Debian-avbildningarna som används i det här exemplet):

    USER root
    RUN apt-get update && apt-get install -y curl
    USER $APP_UID
    

    Notera

    Om du använder en Linux-distribution, till exempel Alpine, som inte stöder apt-getkan du prova RUN apk --no-cache add curl i stället.

    Dessa Docker Compose-funktioner kräver en egenskapsinställning i Docker Compose-projektfilen (.dcproj). Ange egenskapen DependencyAwareStart till true:

    <PropertyGroup>
       <!-- existing properties -->
       <DependencyAwareStart>true</DependencyAwareStart>
    </PropertyGroup>
    

    Den här egenskapen aktiverar ett annat sätt att starta containrarna för felsökning som stöder funktionerna för tjänstberoende.

    Med dessa ändringar startar inte webfrontend-tjänsten förrän mywebapi startar och hanterar en webbbegäran.

  7. Det första projektet som du lägger till containerorkestrering i konfigureras för att startas när du kör eller felsöker. Du kan konfigurera startåtgärden i Project Properties för Docker Compose-projektet. På projektnoden Docker Compose högerklickar du för att öppna snabbmenyn och väljer sedan Egenskapereller använder Alt+Retur. Till exempel kan du ändra sidan som läses in genom att anpassa Service-URL-egenskapen .

    Skärmbild av Docker Compose-projektegenskaper.

  8. Tryck på F5. Här är vad du ser när du startar:

    Skärmbild av webbappen som är igång.

  9. Du kan övervaka containrarna med hjälp av fönstret Containrar. Om du inte ser fönstret använder du sökrutan, trycker på Ctrl+K, Ctrl+Oeller trycker på Ctrl+Q. Under Funktionssökningsöker du efter containersoch väljer Visa>Andra fönster>Behållare i listan.

  10. Expandera Lösningscontainrar noden och välj noden för Docker Compose-projektet för att visa kombinerade loggar i fliken Loggar i det här fönstret.

    Skärmbild som visar fliken Loggar i fönstret Containrar.

    Du kan också välja noden för en enskild container för att visa loggar, miljövariabler, filsystemet och annan information.

Konfigurera startprofiler

  1. Den här lösningen har en Azure Cache for Redis, men det är inte effektivt att återskapa cachecontainern varje gång du startar en felsökningssession. För att undvika den situationen kan du konfigurera ett par startprofiler. Skapa en profil för att starta Azure Cache for Redis. Skapa en andra profil för att starta de andra tjänsterna. Den andra profilen kan använda den cachecontainer som redan körs. Från menyraden kan du använda listrutan bredvid startknappen för att öppna en meny med felsökningsalternativ. Välj Hantera Startinställningar för Docker Compose.

    Skärmbild av menyalternativet Hantera skrivinställningar för felsökning.

    Dialogrutan Hantera Startinställningar för Docker Compose visas. Med den här dialogrutan kan du styra vilken delmängd av tjänster som startas under en felsökningssession, som startas med eller utan felsökningsprogrammet kopplat, samt starttjänsten och URL:en. Se Starta en delmängd av Compose-tjänster.

    Skärmbild av dialogrutan Hantera Startinställningar för Docker Compose.

    Välj Ny för att skapa en ny profil och ge den namnet Start Redis. Ställ sedan in Redis-containern på Starta utan att felsöka, lämna den andra inställd på Starta inteoch välj Spara.

    Skärmbild som visar hur du skapar Redis-profilen som endast startar Redis-tjänsten.

    Skapa sedan en annan profil Start My Services som inte startar Redis, men startar de andra två tjänsterna.

    Skärmbild som visar hur du skapar profilen Tjänster som startar de andra tjänsterna.

    (Valfritt) Skapa en tredje profil Start All för att starta allt. Du kan välja Starta utan att felsöka för Redis.

  2. Välj Starta Redis i listrutan i visual studio-verktygsfältet. Redis-containern bygger och startar utan felsökning. Du kan använda fönstret Containers för att se att det körs. Välj sedan Starta mina tjänster i listrutan och tryck på F5 för att starta dem. Nu kan du hålla cachecontainern igång under många efterföljande felsökningssessioner. Varje gång du använder Starta mina tjänsteranvänder dessa tjänster samma cachecontainer.

Grattis, du kör ett Docker Compose-program med en anpassad Docker Compose-profil.

Nästa steg

Titta på alternativen för att distribuera dina containrar till Azure.

Se även

Docker Compose

Containerverktyg