Поделиться через


Руководство по созданию многоконтейнерного приложения с помощью Docker Compose

В этом руководстве вы узнаете, как управлять несколькими контейнерами и взаимодействовать между ними при использовании средств контейнеров в Visual Studio. Для управления несколькими контейнерами требуется оркестрация контейнеров и требуется оркестратор, например Docker Compose. Для этих процедур используется Docker Compose. Docker Compose отлично подходит для локальной отладки и тестирования в ходе цикла разработки.

Полный пример, который вы создали в этом руководстве, можно найти на сайте GitHub https://github.com/MicrosoftDocs/vs-tutorial-samples в папке docker/ComposeSample.

Предпосылки

  • Docker Desktop
  • Visual Studio с установленной рабочей нагрузкой разработки ASP.NET и веб-разработки, рабочей нагрузкой разработки Azure и (или) кроссплатформенной рабочей нагрузкой разработки .NET . Эта установка включает пакет SDK для .NET.
  • Docker Desktop
  • Visual Studio с установленной рабочей нагрузкой разработки ASP.NET и веб-разработки, рабочей нагрузкой разработки Azure и (или) кроссплатформенной рабочей нагрузкой разработки .NET . Эта установка включает пакет SDK для .NET.

Создание проекта веб-приложения

В Visual Studio создайте проект ASP.NET Core Web App с именем WebFrontEnd, чтобы создать веб-приложение с помощью страниц Razor.

Не нажимайте кнопку "Включить поддержку контейнеров". Вы добавите поддержку контейнеров позже в процессе.

Снимок экрана: экран дополнительных сведений при создании веб-проекта. Параметр включения поддержки контейнеров не выбран.

Создание проекта веб-API

  1. Добавьте проект в то же решение и вызовите его MyWebAPI. Выберите API в качестве типа проекта и снимите флажок " Настроить для HTTPS".

    Замечание

    В этом проекте мы используем только ПРОТОКОЛ HTTPS для обмена данными с клиентом, а не для обмена данными между контейнерами в одном веб-приложении. Только WebFrontEnd нуждается в HTTPS, и код в примерах предполагает, что вы сняли этот флажок для HTTPS. Как правило, сертификаты разработчика .NET, используемые Visual Studio, поддерживаются только для внешних запросов к контейнерам, а не для запросов контейнеров в контейнер.

    Снимок экрана: создание проекта веб-API.

  2. Добавьте поддержку кэша Azure для Redis. Добавьте пакет Microsoft.Extensions.Caching.StackExchangeRedis NuGet (не 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";
       });
    
  3. Добавьте директивы using в Program.cs, Microsoft.Extensions.Caching.Distributed и Microsoft.Extensions.Caching.StackExchangeRedis.

    using Microsoft.Extensions.Caching.Distributed;
    using Microsoft.Extensions.Caching.StackExchangeRedis;
    
  4. В проекте Web 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;
            }
        }
    }
    

    Служба увеличивает счетчик при каждом доступе к странице и сохраняет счетчик в кэше.

Добавление кода для вызова веб-API

  1. WebFrontEnd В проекте откройте файл Index.cshtml.cs и замените OnGet метод следующим кодом.

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

    Замечание

    В реальном коде вы не должны освобождать HttpClient после каждого запроса. Рекомендации см. в разделе "Использование HttpClientFactory" для реализации устойчивых HTTP-запросов.

    Универсальный код ресурса (URI) ссылается на имя службы, определенное в файле docker-compose.yml. Docker Compose настраивает сеть по умолчанию для обмена данными между контейнерами с помощью перечисленных имен служб в качестве узлов.

    Приведенный здесь код работает с .NET 8 и более поздними версиями, который настраивает учетную запись пользователя в Dockerfile без прав администратора и предоставляет порт 8080, так как порт HTTP по умолчанию 80 недоступен без повышенных привилегий.

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

  1. В проекте выберите WebFrontEnd. Откроется диалоговое окно "Параметры поддержки Docker ".

  2. Выберите Docker Compose.

  3. Visual Studio 17.12 и более поздних версий Выберите параметры формирования шаблонов для проекта WebFrontEnd.

    Снимок экрана: диалоговое окно

    Visual Studio 17.11 и более ранних версий Выберите целевую ОС, например Linux.

    Снимок экрана: выбор целевой ОС.

    Visual Studio создает файл docker-compose.yml и еще один .dockerignore файл в узле docker-compose в решении, и этот проект отображается полужирным шрифтом, чтобы показать, что он является стартовым проектом.

    Снимок экрана: обозреватель решений с добавленным проектом Docker Compose.

    Docker-compose.yml отображается следующим образом:

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

    Файл .dockerignore содержит типы файлов и расширения, которые не нужно включать в контейнер Docker. Эти файлы обычно связаны с средой разработки и системой управления версиями, а не частью приложения или службы, которую вы разрабатываете.

    Дополнительные сведения о выполняемых командах см. в разделе "Средства контейнеров " области вывода. Вы увидите, что средство docker-compose командной строки используется для настройки и создания контейнеров среды выполнения.

  4. В проекте Web API снова щелкните правой кнопкой мыши на элемент проекта и выберите Добавить>Поддержка оркестратора контейнеров. Выберите Docker Compose и выберите ту же целевую ОС.

    Замечание

    На этом шаге Visual Studio предложит создать Dockerfile. Если вы делаете это в проекте, который уже поддерживает Docker, вам будет предложено перезаписать существующий Файл Dockerfile. Если вы внесли изменения в Dockerfile, которые вы хотите сохранить, выберите нет.

    Visual Studio вносит некоторые изменения в docker-compose файл YML. Теперь обе услуги включены.

    services:
      webfrontend:
        image: ${DOCKER_REGISTRY-}webfrontend
        build:
          context: .
          dockerfile: WebFrontEnd/Dockerfile
    
      mywebapi:
        image: ${DOCKER_REGISTRY-}mywebapi
        build:
          context: .
          dockerfile: MyWebAPI/Dockerfile
    
  5. Добавьте кэш в docker-compose.yml файл:

    redis:
       image: redis
    

    Убедитесь, что отступ находится на том же уровне, что и другие два сервиса.

  6. (Visual Studio 17.13 или более поздней версии) Зависимые службы демонстрируют общую проблему. HTTP-запрос на главной странице внешнего интерфейса может выполняться немедленно при запуске приложения, прежде чем mywebapi служба будет готова к получению веб-запросов. Если вы используете Visual Studio 17.13 или более поздней версии, вы можете использовать функции depends_on Docker Compose и healthcheck в docker-compose.yml , чтобы начать проекты в правильной последовательности, и подготовить их к выполнению запросов при необходимости. Смотрите раздел Docker Compose — порядок запуска.

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

    В этом примере проверка работоспособности используется curl для проверки готовности службы к обработке запросов. Если образ, который вы используете, не имеет установленного curl, добавьте строки на этап base файла Dockerfile MyWebAPI для его установки. Для этого шага требуются повышенные привилегии, но вы можете восстановить обычные привилегии пользователя после его установки, как показано здесь (для образов Debian, используемых в этом примере):

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

    Замечание

    Если вы используете дистрибутив Linux, например Alpine, который не поддерживает apt-get, попробуйте вместо этого RUN apk --no-cache add curl.

    Для этих функций Docker Compose требуется параметр свойства в файле проекта Docker Compose (.dcproj). Задайте для свойства DependencyAwareStart значение true:

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

    Это свойство активирует другой способ запуска контейнеров для отладки, поддерживающего функции зависимости сервисов.

    С этими изменениями служба webfrontend не запустится, пока mywebapi не начнется и успешно не обработает веб-запрос.

  7. Первый проект, к которому вы добавляете оркестрацию контейнеров, настраивается для автоматического запуска при запуске или отладке. Действие запуска можно настроить в свойствах проекта Docker Compose. На узле проекта Docker Compose щелкните правой кнопкой мыши, чтобы открыть контекстное меню, а затем выберите пункт "Свойства" или используйте ALT+ВВОД. Например, можно изменить страницу, загруженную путем настройки свойства URL-адреса службы .

    Снимок экрана: свойства проекта Docker Compose.

  8. Нажмите клавишу F5. Вот что вы видите при запуске:

    Снимок экрана: запуск веб-приложения.

  9. Контейнеры можно отслеживать с помощью окна "Контейнеры ". Если окно не отображается, используйте поле поиска, нажмите клавиши CTRL+, CTRL+O или нажмите клавиши CTRL+Q. В разделе "Поиск функций" найдите containersи выберите в списке "Просмотреть>Другие окна Windows>Контейнеры.

  10. Разверните узел "Контейнеры решений " и выберите узел для проекта Docker Compose, чтобы просмотреть объединенные журналы на вкладке "Журналы " этого окна.

    Снимок экрана: просмотр вкладки

    Вы также можете выбрать узел для отдельного контейнера для просмотра журналов, переменных среды, файловой системы и других сведений.

Настройка профилей запуска

  1. В этом решении используется кэш Azure для Redis, но неэффективно перестраивать контейнер кэша при каждом запуске сеанса отладки. Чтобы избежать этой ситуации, можно настроить несколько профилей запуска. Создайте один профиль, чтобы запустить кэш Azure для Redis. Создайте второй профиль, чтобы запустить другие службы. Второй профиль может использовать контейнер кэша, который уже запущен. В строке меню можно использовать раскрывающийся список рядом с кнопкой "Пуск", чтобы открыть меню с параметрами отладки. Выберите "Управление параметрами запуска Docker Compose".

    Снимок экрана пункта меню

    Откроется диалоговое окно "Управление параметрами запуска Docker Compose ". В этом диалоговом окне можно контролировать, какое подмножество служб запускается во время сеанса отладки, которое запускается с присоединенным отладчиком или без нее, а также службу запуска и URL-адрес. См. раздел Запуск подмножества служб Compose.

    Снимок экрана: диалоговое окно

    Выберите "Создать" , чтобы создать новый профиль и назовите его Start Redis. Затем установите для контейнера Redis значение Start без отладки, оставьте другой параметр "Не запускать" и нажмите кнопку "Сохранить".

    Снимок экрана: создание профиля Redis, запускающего только службу Redis.

    Затем создайте другой профиль Start My Services , который не запускает Redis, но запускает другие две службы.

    Снимок экрана: создание профиля служб, запускающего другие службы.

    (Необязательно) Создайте третий профиль Start All , чтобы начать все. Вы можете выбрать "Пуск" без отладки для Redis.

  2. Выберите "Пуск Redis" в раскрывающемся списке на главной панели инструментов Visual Studio. Контейнер Redis создает и запускается без отладки. Окно "Контейнеры" можно использовать, чтобы увидеть, что оно работает. Затем выберите "Пуск мои службы " из раскрывающегося списка и нажмите клавишу F5 , чтобы запустить их. Теперь контейнер кэша можно запускать во многих последующих сеансах отладки. При каждом использовании Запустить мои службы эти службы используют один и тот же контейнер кэша.

Поздравляем, вы запускаете приложение Docker Compose с пользовательским профилем Docker Compose.

Дальнейшие шаги

Ознакомьтесь с параметрами развертывания контейнеров в Azure. Если вы готовы развернуть приложения контейнеров в Azure, см. статью "Развертывание многоконтейнерного приложения в Azure Container Apps".

См. также

Docker Compose

Инструменты контейнеров