Руководство по созданию многоконтейнерного приложения с помощью Docker Compose
В этом руководстве вы узнаете, как управлять несколькими контейнерами и взаимодействовать между ними при использовании средств контейнеров в Visual Studio. Для управления несколькими контейнерами требуется оркестрация контейнеров и оркестратор, например Docker Compose или Service Fabric. Для этих процедур используется Docker Compose. Docker Compose отлично подходит для локальной отладки и тестирования в течение цикла разработки.
Полный пример, который вы создали в этом руководстве, можно найти на сайте GitHub https://github.com/MicrosoftDocs/vs-tutorial-samples в папке docker/ComposeSample.
Необходимые компоненты
- Docker Desktop
- Visual Studio 2019 с установленной рабочей нагрузкой Веб-разработка, Средства Azure и (или) Кроссплатформенная разработка .NET.
- Docker Desktop
- Visual Studio 2022 с установленной рабочей нагрузкой Веб-разработка, Azure Tools и (или) Кроссплатформенная разработка .NET. Эта установка включает средства разработки .NET 8.
Создание проекта веб-приложения
В Visual Studio создайте проект Веб-приложение ASP.NET Core с именем WebFrontEnd
для создания веб-приложения с Razor Pages.
Не нажимайте кнопку "Включить поддержку Docker". Вы добавите поддержку Docker позже в процессе.
Примечание.
В Visual Studio 2022 17.2 и более поздних версий для этого проекта можно использовать Функции Azure.
Не нажимайте кнопку "Включить поддержку Docker". Вы добавите поддержку Docker позже в процессе.
Создание проекта веб-API
Добавьте еще один проект в то же решение и назовите его MyWebAPI. Выберите тип проекта API и снимите флажок Настроить для HTTPS. В данном случае протокол SSL используется только для обмена данными с клиентом, но не для обмена данными между контейнерами в пределах веб-приложения. Только для WebFrontEnd
необходим протокол HTTPS, а в коде в примерах предполагается, что флажок снят. Используемые Visual Studio сертификаты разработчика .NET обычно позволяют выполнять запросы к контейнеру извне, а не запросы между контейнерами.
Добавьте еще один проект в то же решение и назовите его WebAPI. Выберите тип проекта API и снимите флажок Настроить для HTTPS. В данном случае протокол SSL используется только для обмена данными с клиентом, но не для обмена данными между контейнерами в пределах веб-приложения. Только для
WebFrontEnd
необходим протокол HTTPS, а в коде в примерах предполагается, что флажок снят. Используемые Visual Studio сертификаты разработчика .NET обычно позволяют выполнять запросы к контейнеру извне, а не запросы между контейнерами.Добавьте поддержку Redis Cache. Добавьте пакет NuGet
Microsoft.Extensions.Caching.StackExchangeRedis
(неStackExchange.Redis
). В файле Program.cs добавьте следующие строки сразу перед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"; });
Добавьте директивы using в файл Program.cs для
Microsoft.Extensions.Caching.Distributed
иMicrosoft.Extensions.Caching.StackExchangeRedis
.using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Caching.StackExchangeRedis;
В проекте веб-API удалите существующие файлы WeatherForecast.cs и Controllers/WeatherForecastController.cs, а затем в папке Controllers добавьте файл CounterController.cs со следующим содержимым:
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; } } }
Служба увеличивает значение счетчика при каждом доступе к странице и сохраняет счетчик в Redis Cache.
Добавление кода для вызова веб-API
В проекте
WebFrontEnd
откройте файл Index.cshtml.cs и замените текст методаOnGet
следующим кодом.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(); } }
Примечание.
В реальном коде не следует удалять
HttpClient
после каждого запроса. Рекомендации см. в разделе Использование HttpClientFactory для реализации устойчивых HTTP-запросов.В файл Index.cshtml добавьте строку для отображения
ViewData["Message"]
, чтобы файл выглядел примерно так:@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>
(Только для ASP.NET 2.x) Теперь перейдите в проект веб-API и добавьте в контроллер Values код с пользовательским сообщением API для вызова, который вы добавили из webfrontend.
// GET api/values/5 [HttpGet("{id}")] public ActionResult<string> Get(int id) { return "webapi (with value " + id + ")"; }
Примечание.
В .NET Core 3.1 и более поздних версий можно использовать предоставленный API WeatherForecast, а не этот дополнительный код. Однако необходимо закомментировать вызов UseHttpsRedirection в проекте веб-API, так как код использует HTTP для вызова, а не HTTPS.
//app.UseHttpsRedirection();
Добавление поддержки Docker Compose
В проекте
WebFrontEnd
выберите Добавить > Container Orchestrator Support (Поддержка оркестратора контейнеров). Появится диалоговое окно Варианты поддержки Docker.Выберите Docker Compose.
Выберите целевую ОС, например Linux.
Visual Studio создаст файлы docker-compose.yml и DOCKERIGNORE в узле docker-compose решения. Этот проект выделен полужирным шрифтом, что значит, что это запускаемый проект.
Файл docker-compose.yml выглядит так:
version: '3.4' services: webfrontend: image: ${DOCKER_REGISTRY-}webfrontend build: context: . dockerfile: WebFrontEnd/Dockerfile
В
version
первой строке указана версия файла Docker Compose. Обычно не следует изменять его, так как он используется средствами для понимания того, как интерпретировать файл.Файл DOCKERIGNORE содержит типы и расширения имен файлов, которые средству Docker не нужно включать в контейнер. Обычно эти файлы связаны со средой разработки и системой управления версиями, а не с самим разрабатываемым приложением или службой.
Сведения о выполняемых командах приводятся в разделе Инструменты для контейнера области выходных данных. Как вы можете видеть, программа командной строки docker-compose используется для настройки и создания контейнеров среды выполнения.
В проекте веб-API еще раз щелкните узел проекта правой кнопкой мыши и выберите пункт Добавить>Container Orchestrator Support (Поддержка оркестратора контейнеров). Выберите Docker Compose, а затем выберите ту же целевую ОС.
Примечание.
На этом этапе Visual Studio предложит создать Dockerfile. Если сделать это для проекта, который уже поддерживает Docker, появится запрос на перезапись существующего файла Dockerfile. Если вы внесли изменения в Dockerfile, которые хотите сохранить, выберите "Нет".
Visual Studio вносит ряд изменений в YML-файл docker-compose. Теперь включены обе службы.
version: '3.4' services: webfrontend: image: ${DOCKER_REGISTRY-}webfrontend build: context: . dockerfile: WebFrontEnd/Dockerfile mywebapi: image: ${DOCKER_REGISTRY-}mywebapi build: context: . dockerfile: MyWebAPI/Dockerfile
Первый проект, в котором вы добавляете оркестрацию контейнеров, настраивается запускаемым при выполнении или отладке. Настроить действие запуска для проекта docker-compose можно в свойствах проекта. Щелкните правой кнопкой мыши узел проекта docker-compose и выберите в контекстном меню пункт Свойства или нажмите клавиши ALT+ВВОД. На снимке экрана ниже показаны свойства, которые требуются для решения в этом руководстве. Например, можно изменить загружаемую страницу, настроив свойство URL-адрес службы.
Вот что вы видите при запуске (версия .NET Core 2.x):
В веб-приложении для .NET 3.1 отображаются данные о погоде в формате JSON.
Теперь предположим, что вам нужно только подключить отладчик к WebFrontEnd, а не проект веб-API. В строке меню вы можете выбрать раскрывающийся список рядом с кнопкой "Пуск", чтобы открыть меню параметров отладки. Выберите в нем Управление параметрами запуска Docker Compose.
Откроется диалоговое окно Управление параметрами запуска Docker Compose. В этом диалоговом окне можно контролировать, какое подмножество служб запускается во время сеанса отладки, которое запускается с присоединенным отладчиком или без нее, а также службу запуска и URL-адрес. См. Запуск подмножества служб Compose.
Выберите Создать, чтобы создать профиль, и назовите его
Debug WebFrontEnd only
. Затем задайте для проекта веб-API параметр Запускать без отладки, оставьте для проекта WebFrontEnd параметр запуска с отладкой и нажмите Сохранить.Новая конфигурация будет выбрана как конфигурацию по умолчанию при следующем нажатии клавиши F5.
Нажмите клавишу F5, чтобы подтвердить правильную работу.
Поздравляем! Вы запустили приложение Docker Compose с пользовательским профилем Docker Compose.
В проекте
WebFrontEnd
откройте файл Index.cshtml.cs и замените текст методаOnGet
следующим кодом.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}"; } }
Примечание.
В реальном коде не следует удалять
HttpClient
после каждого запроса. Рекомендации см. в разделе Использование HttpClientFactory для реализации устойчивых HTTP-запросов.В файл Index.cshtml добавьте строку для отображения
ViewData["Message"]
, чтобы файл выглядел примерно так:@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>
Этот код отображает значение счетчика, возвращаемого из проекта веб-API.
Добавление поддержки Docker Compose
В проекте
WebFrontEnd
выберите Добавить > Container Orchestrator Support (Поддержка оркестратора контейнеров). Появится диалоговое окно Варианты поддержки Docker.Выберите Docker Compose.
Выберите целевую ОС, например Linux.
Visual Studio создаст файлы docker-compose.yml и DOCKERIGNORE в узле docker-compose решения. Этот проект выделен полужирным шрифтом, что значит, что это запускаемый проект.
Файл docker-compose.yml выглядит так:
version: '3.4' services: webfrontend: image: ${DOCKER_REGISTRY-}webfrontend build: context: . dockerfile: WebFrontEnd/Dockerfile
В
version
первой строке указана версия файла Docker Compose. Обычно не следует изменять его, так как он используется средствами для понимания того, как интерпретировать файл.Файл DOCKERIGNORE содержит типы и расширения имен файлов, которые средству Docker не нужно включать в контейнер. Обычно эти файлы связаны со средой разработки и системой управления версиями, а не с самим разрабатываемым приложением или службой.
Сведения о выполняемых командах приводятся в разделе Инструменты для контейнера области выходных данных. Как вы можете видеть, программа командной строки docker-compose используется для настройки и создания контейнеров среды выполнения.
В проекте веб-API еще раз щелкните узел проекта правой кнопкой мыши и выберите пункт Добавить>Container Orchestrator Support (Поддержка оркестратора контейнеров). Выберите Docker Compose, а затем выберите ту же целевую ОС.
Примечание.
На этом этапе Visual Studio предложит создать Dockerfile. Если сделать это для проекта, который уже поддерживает Docker, появится запрос на перезапись существующего файла Dockerfile. Если вы внесли изменения в Dockerfile, которые хотите сохранить, выберите "Нет".
Visual Studio вносит ряд изменений в YML-файл docker-compose. Теперь включены обе службы.
version: '3.4' services: webfrontend: image: ${DOCKER_REGISTRY-}webfrontend build: context: . dockerfile: WebFrontEnd/Dockerfile mywebapi: image: ${DOCKER_REGISTRY-}mywebapi build: context: . dockerfile: MyWebAPI/Dockerfile
Добавьте кэш Redis Сache в файл
docker.compose.yml
:redis: image: redis
Убедитесь, что отступ находится на том же уровне, что и у двух других служб.
Первый проект, в котором вы добавляете оркестрацию контейнеров, настраивается запускаемым при выполнении или отладке. Настроить действие запуска для проекта docker-compose можно в свойствах проекта. Щелкните правой кнопкой мыши узел проекта docker-compose и выберите в контекстном меню пункт Свойства или нажмите клавиши ALT+ВВОД. Например, можно изменить загружаемую страницу, настроив свойство URL-адрес службы.
Нажмите клавишу F5. Вот что вы увидите при запуске:
Контейнеры можно отслеживать с помощью окна "Контейнеры ". Если окно не отображается, используйте поле поиска, нажмите клавиши CTRL K, CTRL++O или нажмите клавиши CTRL+Q. В разделе "Поиск компонентов" найдите
containers
и выберите "Просмотреть>другие контейнеры Windows>" в списке.Разверните узел "Контейнеры решений" и выберите узел для проекта Docker Compose, чтобы просмотреть объединенные журналы на вкладке "Журналы" этого окна.
Вы также можете выбрать узел для отдельного контейнера для просмотра журналов, переменных среды, файловой системы и других сведений.
Настройка профилей запуска
Это решение использует Redis Cache, но не эффективно перестраивать контейнер Redis Cache при каждом запуске сеанса отладки. Чтобы избежать этой ситуации, можно настроить несколько профилей запуска. Создайте один профиль для запуска кэша Redis. Создайте второй профиль, чтобы запустить другие службы. Второй профиль может использовать контейнер кэша Redis, который уже запущен. В строке меню можно использовать раскрывающийся список рядом с кнопкой "Пуск", чтобы открыть меню с параметрами отладки. Выберите "Управление Docker Compose Launch Параметры".
Откроется диалоговое окно Управление параметрами запуска Docker Compose. В этом диалоговом окне можно контролировать, какое подмножество служб запускается во время сеанса отладки, которое запускается с присоединенным отладчиком или без нее, а также службу запуска и URL-адрес. См. Запуск подмножества служб Compose.
Выберите Создать, чтобы создать профиль, и назовите его
Start Redis
. Затем установите для контейнера Redis значение Запуск без отладки, для других оставьте значение Не запускать и нажмите кнопку Сохранить.Затем создайте еще один профиль
Start My Services
, который не запускает Redis, но запускает две другие службы.(Необязательно.) Создайте третий профиль
Start All
, чтобы запускать все. Можно также выбрать пункт Запуск без отладки для Redis.В раскрывающемся списке на главной панели инструментов Visual Studio выберите команду Start Redis (Запустить Redis) и нажмите клавишу F5. Произойдут сборка и запуск контейнера Redis. В окне Контейнеры можно убедиться, что он запущен. Затем выберите Start My Services (Запустить мои службы) в раскрывающемся списке и нажмите клавишу F5, чтобы запустить службы. Теперь можно поддерживать работу контейнера Redis Сache во многих последующих сеансах отладки. При каждом запуске служб эти службы используют один и тот же контейнер кэша Redis.
Поздравляем! Вы запустили приложение Docker Compose с пользовательским профилем Docker Compose.
Следующие шаги
Ознакомьтесь с вариантами развертывания контейнеров в Azure.