Samouczek: tworzenie aplikacji z wieloma kontenerami za pomocą narzędzia Docker Compose
Z tego samouczka dowiesz się, jak zarządzać więcej niż jednym kontenerem i komunikować się między nimi podczas korzystania z narzędzi kontenerów w programie Visual Studio. Zarządzanie wieloma kontenerami wymaga orkiestracji kontenerów oraz użycia orkiestratora, takiego jak Docker Compose lub Service Fabric. W przypadku tych procedur należy użyć narzędzia Docker Compose. Narzędzie Docker Compose doskonale nadaje się do lokalnego debugowania i testowania w trakcie cyklu programowania.
Ukończony przykład utworzony w tym samouczku można znaleźć w witrynie GitHub pod adresem https://github.com/MicrosoftDocs/vs-tutorial-samples
w folderze docker/ComposeSample.
Warunki wstępne
- Docker Desktop
- programu Visual Studio 2019 z zainstalowanym obciążeniem Web Development, Azure Tools oraz/lub programowania wieloplatformowego .NET
- Docker Desktop
- program Visual Studio 2022 z zainstalowanym obciążeniem Tworzenie aplikacji internetowych, Narzędzi platformy Azure i/lub obciążenia programowania międzyplatformowego platformy .NET. Ta instalacja obejmuje narzędzia programistyczne platformy .NET 8.
Tworzenie projektu aplikacji internetowej
W programie Visual Studio utwórz projekt aplikacji internetowej ASP.NET Core o nazwie WebFrontEnd
, służący do tworzenia aplikacji internetowej ze stronami Razor.
Nie wybieraj włącz obsługę platformy Docker. W dalszej części tego procesu dodasz obsługę platformy Docker.
Nie wybieraj włącz obsługę platformy Docker. W dalszej części tego procesu dodasz obsługę platformy Docker.
Tworzenie projektu Web API
Dodaj projekt do tego samego rozwiązania i nazwij go MyWebAPI. Wybierz interfejs API jako typ projektu i wyczyść pole wyboru Configure for HTTPS. W tym projekcie używamy tylko protokołu SSL do komunikacji z klientem, a nie komunikacji między kontenerami w tej samej aplikacji internetowej. Tylko WebFrontEnd
wymaga protokołu HTTPS, a kod w przykładach zakłada, że pole wyboru zostało wyczyszczone. Ogólnie rzecz biorąc, certyfikaty dla deweloperów platformy .NET używane przez program Visual Studio są obsługiwane tylko w przypadku żądań zewnętrznych do kontenerów, a nie dla żądań kontenera do kontenera.
Dodaj projekt do tego samego rozwiązania i nazwij go MyWebAPI. Wybierz interfejs API jako typ projektu i wyczyść pole wyboru Configure for HTTPS.
Notatka
W tym projekcie używamy tylko protokołu HTTPS do komunikacji z klientem, a nie komunikacji między kontenerami w tej samej aplikacji internetowej. Tylko
WebFrontEnd
wymaga protokołu HTTPS, a kod w przykładach zakłada, że odznaczyłeś to pole wyboru. Ogólnie rzecz biorąc, certyfikaty dla deweloperów platformy .NET używane przez program Visual Studio są obsługiwane tylko w przypadku żądań zewnętrznych do kontenerów, a nie dla żądań kontenera do kontenera.Dodano obsługę usługi Azure Cache for Redis. Dodaj pakiet NuGet
Microsoft.Extensions.Caching.StackExchangeRedis
(nieStackExchange.Redis
). W Program.csdodaj następujące wiersze tuż przedvar 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"; });
Dodaj dyrektywy using w
Program.cs
dlaMicrosoft.Extensions.Caching.Distributed
iMicrosoft.Extensions.Caching.StackExchangeRedis
.using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Caching.StackExchangeRedis;
W projekcie internetowego interfejsu API usuń istniejące kontrolery
WeatherForecast.cs
i /WeatherForecastController.cs, a następnie dodaj nowy plik w folderze Kontrolery CounterController.csz następującą zawartością: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; } } }
Usługa zwiększa licznik za każdym razem, gdy strona jest odwiedzana, a licznik jest przechowywany w pamięci podręcznej.
Dodaj kod do wywołania Web API
W projekcie
WebFrontEnd
otwórz plik Index.cshtml.cs i zastąp metodęOnGet
poniższym kodem.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(); } }
Notatka
W rzeczywistym kodzie nie należy usuwać
HttpClient
po każdym żądaniu. Aby uzyskać najlepsze rozwiązania, zobacz Implementowanie odpornych żądań HTTPza pomocą metody HttpClientFactory.W pliku
Index.cshtml
dodaj wiersz do wyświetleniaViewData["Message"]
, aby plik wyglądał podobnie do następującego kodu:@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>
(tylko ASP.NET 2.x) Teraz w projekcie Web API dodaj kod do kontrolera Values, aby dostosować komunikat zwrócony przez API dla wywołania, które dodałeś z webfrontend.
// GET api/values/5 [HttpGet("{id}")] public ActionResult<string> Get(int id) { return "webapi (with value " + id + ")"; }
Notatka
W programie .NET Core 3.1 lub nowszym można użyć podanego interfejsu API WeatherForecast, a nie tego dodatkowego kodu. Należy jednak oznaczyć wywołanie UseHttpsRedirection jako komentarz w projekcie Web API, ponieważ kod używa protokołu HTTP do wywołania, a nie HTTPS.
//app.UseHttpsRedirection();
Dodawanie obsługi narzędzia Docker Compose
W projekcie
WebFrontEnd
wybierz opcję Dodaj obsługę orkiestratora kontenerów >. Zostanie wyświetlone okno dialogowe Opcje obsługi platformy Docker.Wybierz Docker Compose.
Wybierz docelowy system operacyjny, na przykład Linux.
Program Visual Studio tworzy plik docker-compose.yml i plik
.dockerignore
w węźle docker-compose w rozwiązaniu, a projekt pojawia się pogrubiony, co wskazuje, że jest to projekt startowy.docker-compose.yml wygląda w następujący sposób:
services: webfrontend: image: ${DOCKER_REGISTRY-}webfrontend build: context: . dockerfile: WebFrontEnd/Dockerfile
version
określony w pierwszym wierszu to wersja pliku Docker Compose . Zwykle nie należy go zmieniać, ponieważ jest on używany przez narzędzia do zrozumienia sposobu interpretowania pliku.Plik
.dockerignore
zawiera typy plików i rozszerzenia, których nie chcesz, aby Docker uwzględniał w kontenerze. Te pliki są zwykle kojarzone ze środowiskiem projektowym i kontrolą źródła, a nie częścią tworzonej aplikacji lub usługi.Spójrz na sekcję Container Tools panelu wyjściowego, aby uzyskać szczegóły na temat uruchamianych poleceń. Zobaczysz, że narzędzie wiersza polecenia
docker-compose
służy do konfigurowania i tworzenia kontenerów środowiska uruchomieniowego.W projekcie internetowego interfejsu API ponownie kliknij prawym przyciskiem myszy węzeł projektu, a następnie wybierz pozycję Dodaj obsługę orkiestratora kontenerów>. Wybierz docker Compose, a następnie wybierz ten sam docelowy system operacyjny.
Notatka
W tym kroku program Visual Studio będzie oferować tworzenie pliku Dockerfile. Jeśli zrobisz to w projekcie, który ma już obsługę platformy Docker, zostanie wyświetlony monit o zastąpienie istniejącego pliku Dockerfile. Jeśli wprowadzono zmiany w pliku Dockerfile, które chcesz zachować, wybierz pozycję Nie.
Program Visual Studio wprowadza pewne zmiany w pliku Docker Compose YML. Teraz oba usługi są uwzględniane.
services: webfrontend: image: ${DOCKER_REGISTRY-}webfrontend build: context: . dockerfile: WebFrontEnd/Dockerfile mywebapi: image: ${DOCKER_REGISTRY-}mywebapi build: context: . dockerfile: MyWebAPI/Dockerfile
Pierwszy projekt, do którego dodajesz orkiestrację kontenerów, jest skonfigurowany do uruchomienia podczas uruchamiania lub debugowania. Akcję uruchamiania można skonfigurować w właściwościach projektu dla projektu Docker Compose. W węźle projektu Docker Compose kliknij prawym przyciskiem myszy, aby otworzyć menu kontekstowe, a następnie wybierz pozycję Właściwościlub użyj Alt+Enter. Poniższy zrzut ekranu przedstawia właściwości, które mogą być pożądane dla użytego tutaj rozwiązania. Można na przykład zmienić załadowaną stronę, dostosowując właściwość adresu URL usługi.
Oto, co widzisz po uruchomieniu (wersja .NET Core 2.x):
Aplikacja internetowa dla platformy .NET 3.1 wyświetla dane pogodowe w formacie JSON.
Teraz załóżmy, że interesuje Cię tylko dołączenie debugera do aplikacji WebFrontEnd, a nie projektu Web API. Na pasku menu możesz użyć listy rozwijanej obok przycisku Start, aby wyświetlić menu opcji debugowania. wybierz Zarządzaj ustawieniami uruchamiania platformy Docker Compose.
Pojawi się okno dialogowe Zarządzanie ustawieniami uruchamiania Docker Compose. Za pomocą tego okna dialogowego można kontrolować, który podzbiór usług jest uruchamiany podczas sesji debugowania, która jest uruchamiana z dołączonym debugerem lub bez niego, oraz usługę uruchamiania i adres URL. Zobacz Uruchamianie podzestawu usług Compose.
Wybierz pozycję Nowy, aby utworzyć nowy profil i nadaj mu nazwę
Debug WebFrontEnd only
. Następnie ustaw projekt internetowego interfejsu API na Rozpocznij bez debugowania, pozostaw projekt WebFrontEnd ustawiony na rozpoczęcie od debugowania, a następnie wybierz pozycję Zapisz.Nowa konfiguracja została wybrana jako domyślna dla kolejnych F5.
Naciśnij F5, aby potwierdzić, że działa zgodnie z oczekiwaniami.
Gratulacje, korzystasz z aplikacji Docker Compose z niestandardowym profilem Docker Compose.
W projekcie
WebFrontEnd
otwórz plik Index.cshtml.cs i zastąp metodęOnGet
poniższym kodem.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}"; } }
Notatka
W rzeczywistym kodzie nie należy usuwać
HttpClient
po każdym żądaniu. Aby uzyskać najlepsze rozwiązania, zobacz Implementowanie odpornych żądań HTTPza pomocą metody HttpClientFactory.Podany identyfikator URI odwołuje się do nazwy usługi zdefiniowanej w pliku docker-compose.yml. Docker Compose konfiguruje domyślną sieć na potrzeby komunikacji między kontenerami przy użyciu wymienionych nazw usług jako hostów.
Pokazany tutaj kod działa z platformą .NET 8 i nowszym, który konfiguruje konto użytkownika w pliku Dockerfile bez uprawnień administratora i uwidacznia port 8080, ponieważ domyślny port HTTP 80 nie jest dostępny bez podniesionych uprawnień.
W pliku
Index.cshtml
dodaj wiersz do wyświetleniaViewData["Message"]
, aby plik wyglądał podobnie do następującego kodu:@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>
Ten kod wyświetla wartość licznika zwracaną przez projekt Web API. Zwiększa się za każdym razem, gdy użytkownik uzyskuje dostęp do lub odświeża stronę.
Dodawanie obsługi narzędzia Docker Compose
W projekcie
WebFrontEnd
wybierz pozycję Dodaj obsługę orkiestratora kontenerów >. Zostanie wyświetlone okno dialogowe Opcje obsługi platformy Docker.Wybierz Docker Compose.
Visual Studio 17.12 i późniejszych Wybierz opcje szkieletowania projektu WebFrontEnd.
Visual Studio 17.11 i starsze Wybierz docelowy system operacyjny, na przykład Linux.
Program Visual Studio tworzy plik docker-compose.yml i plik
.dockerignore
w węźle docker-compose w rozwiązaniu, a projekt jest wyświetlany pogrubioną czcionką, co pokazuje, że jest to projekt startowy.docker-compose.yml ma następującą postać:
services: webfrontend: image: ${DOCKER_REGISTRY-}webfrontend build: context: . dockerfile: WebFrontEnd/Dockerfile
Plik
.dockerignore
zawiera typy plików i rozszerzenia, których nie chcesz dołączać w Dockerze do kontenera. Te pliki są zwykle kojarzone ze środowiskiem projektowym i kontrolą źródła, a nie częścią tworzonej aplikacji lub usługi.Zapoznaj się z sekcją Container Tools okienka danych wyjściowych, aby uzyskać szczegółowe informacje o uruchamianych poleceniach. Zobaczysz, że narzędzie wiersza polecenia
docker-compose
służy do konfigurowania i tworzenia kontenerów środowiska uruchomieniowego.W projekcie internetowego interfejsu API ponownie kliknij prawym przyciskiem myszy węzeł projektu, a następnie wybierz pozycję Dodaj obsługę orkiestratora kontenerów>. Wybierz docker Compose, a następnie wybierz ten sam docelowy system operacyjny.
Notatka
W tym kroku program Visual Studio będzie oferować tworzenie pliku Dockerfile. Jeśli zrobisz to w projekcie, który ma już obsługę platformy Docker, zostanie wyświetlony monit o zastąpienie istniejącego pliku Dockerfile. Jeśli wprowadzono zmiany w pliku Dockerfile, które chcesz zachować, wybierz pozycję Nie.
Program Visual Studio wprowadza pewne zmiany w pliku
docker-compose
YML. Teraz oba usługi są uwzględniane.services: webfrontend: image: ${DOCKER_REGISTRY-}webfrontend build: context: . dockerfile: WebFrontEnd/Dockerfile mywebapi: image: ${DOCKER_REGISTRY-}mywebapi build: context: . dockerfile: MyWebAPI/Dockerfile
Dodaj pamięć podręczną do pliku
docker-compose.yml
:redis: image: redis
Upewnij się, że wcięcie znajduje się na tym samym poziomie co pozostałe dwie usługi.
(Program Visual Studio 17.13 lub nowszy) Usługi zależne pokazują typowy problem. Żądanie HTTP na stronie głównej frontonu może być uruchamiane natychmiast po uruchomieniu aplikacji, zanim usługa
mywebapi
będzie gotowa do odbierania żądań internetowych. Jeśli używasz programu Visual Studio 17.13 lub nowszego, możesz użyć funkcji narzędzia Docker Composedepends_on
ihealthcheck
w docker-compose.yml, aby projekty zostały uruchomione w odpowiedniej sekwencji i mieć ich gotowość do obsługi żądań, jeśli jest to wymagane. Zobacz Docker Compose - kolejność uruchamiania.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
W tym przykładzie kontrola kondycji używa
curl
w celu sprawdzenia, czy usługa jest gotowa do przetwarzania żądań. Jeśli obraz, którego używasz, nie ma zainstalowanegocurl
, dodaj wiersze do etapubase
w pliku Dockerfile MyWebAPI, aby zainstalować ten element. Ten krok wymaga podniesionych uprawnień, ale można przywrócić normalne uprawnienia użytkownika po zainstalowaniu go, jak pokazano tutaj (w przypadku obrazów Debian używanych w tym przykładzie):USER root RUN apt-get update && apt-get install -y curl USER $APP_UID
Notatka
Jeśli używasz dystrybucji systemu Linux, takiej jak Alpine, to nie obsługuje
apt-get
, spróbujRUN apk --no-cache add curl
zamiast tego.Te funkcje narzędzia Docker Compose wymagają ustawienia właściwości w pliku projektu Docker Compose (
.dcproj
). Ustaw właściwośćDependencyAwareStart
na true:<PropertyGroup> <!-- existing properties --> <DependencyAwareStart>true</DependencyAwareStart> </PropertyGroup>
Ta właściwość aktywuje inny sposób uruchamiania kontenerów na potrzeby debugowania obsługującego funkcje zależności usługi.
Dzięki tym zmianom usługa
webfrontend
nie zostanie uruchomiona do momentu uruchomieniamywebapi
i pomyślnego obsługi żądania internetowego.Pierwszy projekt, do którego dodajesz orkiestrację kontenerów, jest skonfigurowany do uruchomienia podczas uruchamiania lub debugowania. Akcję uruchamiania można skonfigurować w właściwościach projektu dla projektu Docker Compose. W węźle projektu Docker Compose kliknij prawym przyciskiem myszy, aby otworzyć menu kontekstowe, a następnie wybierz Właściwościlub użyj Alt+Enter. Można na przykład zmienić załadowaną stronę, dostosowując właściwość adresu URL usługi.
Naciśnij F5. Oto, co widzisz po uruchomieniu:
Kontenery można monitorować przy użyciu okna kontenerów. Jeśli nie widzisz okna, użyj pola wyszukiwania, naciśnij Ctrl+K, Ctrl+Olub naciśnij Ctrl+Q. W obszarze wyszukiwania funkcjiwyszukaj
containers
i wybierz pozycję Wyświetl>Inne kontenery systemu Windows> z listy.Rozwiń węzeł Kontenery rozwiązań i wybierz węzeł projektu Docker Compose, aby wyświetlić połączone dzienniki na karcie Dzienniki tego okna.
Możesz również wybrać węzeł dla pojedynczego kontenera, aby wyświetlić dzienniki, zmienne środowiskowe, system plików i inne szczegóły.
Konfigurowanie profilów uruchamiania
To rozwiązanie posiada Azure Cache for Redis, ale nie jest wydajne rekonstruowanie kontenera cache za każdym razem, gdy rozpoczyna się sesja debugowania. Aby uniknąć takiej sytuacji, możesz skonfigurować kilka profilów uruchamiania. Utwórz jeden profil, aby uruchomić usługę Azure Cache for Redis. Utwórz drugi profil, aby uruchomić inne usługi. Drugi profil może używać kontenera pamięci podręcznej, który jest już uruchomiony. Na pasku menu możesz użyć listy rozwijanej obok przycisku Start, aby otworzyć menu z opcjami debugowania. Wybierz pozycję Zarządzaj ustawieniami uruchamiania platformy Docker Compose.
Wyskakuje okno dialogowe Zarządzanie ustawieniami uruchamiania platformy Docker Compose. Za pomocą tego okna dialogowego można kontrolować, który podzbiór usług jest uruchamiany podczas sesji debugowania, która jest uruchamiana z dołączonym debugerem lub bez niego, oraz usługę uruchamiania i adres URL. Zobacz Uruchamianie podzestawu usług Compose.
Wybierz pozycję Nowy, aby utworzyć nowy profil i nadaj mu nazwę
Start Redis
. Następnie ustaw kontener Redis na Uruchom bez debugowania, pozostaw drugi kontener w stanie Nie uruchamiaji wybierz opcję Zapisz.Następnie utwórz inny profil
Start My Services
, który nie uruchamia usługi Redis, ale uruchamia pozostałe dwie usługi.(Opcjonalnie) Utwórz trzeci profil
Start All
, aby rozpocząć wszystko. Możesz wybrać Rozpocznij bez debugowania dla Redis.Wybierz pozycję Uruchom Redis z listy rozwijanej na głównym pasku narzędzi programu Visual Studio. Kontener Redis buduje się i uruchamia się bez debugowania. Możesz użyć okna kontenerów, aby zobaczyć, że jest uruchomione. Następnie wybierz pozycję Uruchom moje usługi z listy rozwijanej i naciśnij F5, aby je uruchomić. Teraz możesz zachować działanie kontenera pamięci podręcznej w wielu kolejnych sesjach debugowania. Za każdym razem, gdy używasz Uruchom moje usługi, te usługi używają tego samego kontenera pamięci podręcznej.
Gratulacje, uruchamiasz aplikację Docker Compose z niestandardowym profilem Docker Compose.
Następne kroki
Zapoznaj się z opcjami wdrażania kontenerów na platformie Azure.