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


Рабочий процесс разработки для приложений Docker

Совет

Это содержимое является фрагментом из электронной книги, архитектуры микрослужб .NET для контейнерных приложений .NET, доступных в документации .NET или в виде бесплатного скачиваемого PDF-файла, который можно читать в автономном режиме.

.NET Microservices Architecture for Containerized .NET Applications eBook cover thumbnail.

Жизненный цикл разработки приложений начинается на компьютере разработчика, где разработчик локально программирует приложение на предпочитаемом языке и тестирует его. Независимо от выбранного языка, инфраструктуры и платформы, в рамках этого рабочего процесса разработчик всегда разрабатывает и тестирует контейнеры Docker, но делает это локально.

В каждый контейнер (экземпляр образа Docker) входят следующие компоненты:

  • Выбранная операционная система (например, дистрибутив Linux, Windows Nano Server или Windows Server Core).

  • Файлы, добавленные во время разработки, например исходный код и двоичные файлы и приложения.

  • Сведения о конфигурации, например параметры среды и зависимости.

Рабочий процесс разработки приложений Docker на основе контейнера

В этом разделе описывается рабочий процесс внутреннего цикла разработки приложений на основе контейнера Docker. Рабочий процесс внутреннего цикла означает, что речь идет только о разработке, которая выполняется на компьютере разработчика, не касаясь более широкого рабочего процесса DevOps. Начальные этапы настройки среды здесь не рассматриваются, так как они выполняются только один раз.

Приложение состоит из ваших собственных служб и дополнительных библиотек (зависимостей). Ниже приведены основные шаги, которые обычно выполняются при сборке приложения Docker, как показано на рисунке 5-1.

Diagram showing the seven steps it takes to create a containerized app.

Процесс разработки для приложений Docker: 1 — код приложения, 2 — запись Dockerfile/s, 3 — создание образов, определенных в Dockerfile/s, 4 — (необязательно) Создание служб в файле docker-compose.yml, 5 — запуск контейнера или приложения docker-compose, 6 — тестирование приложения или микрослужб, 7 — отправка в репозиторий и повтор.

Рис. 5-1. Пошаговый рабочий процесс разработки приложения на основе контейнера Docker

В этом разделе подробно описывается весь процесс, и каждый важный шаг объясняется с акцентом на среду Visual Studio.

Если разработка выполняется с помощью редактора и CLI (например, Visual Studio Code и Docker CLI на macOS или Windows), то необходимо знать каждый шаг и обычно более детально, чем при использовании Visual Studio. Дополнительные сведения о работе в среде CLI см. в электронной книге Жизненный цикл приложений в контейнерах Docker с платформами и средствами Майкрософт.

При использовании Visual Studio 2022 многие из этих шагов выполняются автоматически, что значительно повышает производительность. Это особенно справедливо в тех случаях, когда используется Visual Studio 2022 для работы с многоконтейнерными приложениями. Например, всего лишь одним щелчком мыши Visual Studio добавляет Dockerfile и файл docker-compose.yml в проекты с конфигурацией для вашего приложения. При запуске приложения в Visual Studio он создает образ Docker и запускает многоконтейнерное приложение непосредственно в Docker; вы даже можете отлаживать несколько контейнеров одновременно. Эти возможности значительно повышают скорость разработки.

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

Image for Step 1.

Шаг 1. Начало программирования и создание первого приложения или базовой службы

Разработка приложения Docker аналогична разработке приложения без Docker. Разница заключается в том, что при разработке для Docker развертывание и тестирование приложения или служб, работающих в контейнерах Docker, выполняется в локальной среде (в ВМ Linux или напрямую в Windows, если используются контейнеры Windows).

Настройка локальной среды с помощью Visual Studio

Перед началом работы убедитесь, что у вас есть установка Docker Desktop for Windows для Windows, как описано в следующих инструкциях:

Начало работы с Docker Desktop для Windows

Кроме того, вам потребуется Visual Studio 2022 версии 17.0 с установленной рабочей нагрузкой ASP.NET и веб-разработка, как показано на рис. 5–2.

Screenshot of the .NET Core cross-platform development selection.

Рис. 5-2. Выбор рабочей нагрузки ASP.NET и веб-разработка при установке Visual Studio 2022

Можно приступать к программированию приложения в обычной среде .NET (как правило, в .NET Core и более поздних версий, если вы планируете использовать контейнеры) даже до включения Docker в вашем приложении и развертывания и тестирования в Docker. Тем не менее рекомендуется начать работу в Docker как можно быстрее, поскольку это будет реальная среда, и любые проблемы можно будет обнаружить гораздо раньше. Это также рекомендуется потому, что Visual Studio настолько упрощает работу с Docker, что практически все действия очевидны; лучший пример — отладка многоконтейнерного приложения в Visual Studio.

Дополнительные ресурсы

Image for Step 2.

Dockerfile необходим для каждого пользовательского образа, который вы хотите создать; кроме того, Dockerfile потребуется для каждого контейнера, который будет развертываться автоматически из Visual Studio или вручную с помощью Docker CLI (с помощью команд docker run и docker-compose). Если в приложении имеется единственный экземпляр пользовательской службы, необходим один Dockerfile. Если в приложении имеется несколько служб (как в архитектуре на основе микрослужб), потребуется по одному Dockerfile для каждой службы.

Dockerfile размещается в корневой папке приложения или службы. Он содержит команды, которые указывают Docker, как настраивать и запускать приложение или службу в контейнере. Можно вручную создать Dockerfile в коде и добавить его в проект вместе с зависимостями .NET.

В Visual Studio со средствами для Docker эта задача выполняется лишь несколькими щелчками мыши. При создании нового проекта в Visual Studio 2022 можно выбрать параметр Включить поддержку Docker, как показано на рисунке 5–3.

Screenshot showing Enable Docker Support check box.

Рис. 5-3. Включение поддержки Docker при создании нового проекта ASP.NET Core в Visual Studio 2022

Поддержку Docker в существующий проект веб-приложения ASP.NET Core можно также включить, щелкнув правой кнопкой мыши проект в обозревателе решений и выбрав Добавить>Поддержка Docker, как показано на рисунке 5-4.

Screenshot showing the Docker Support option in the Add menu.

Рис. 5-4. Включение поддержки Docker в существующем проекте Visual Studio 2022

Это действие добавляет Dockerfile в проект с необходимой конфигурацией и доступно только для проектов ASP.NET Core.

Аналогичным образом Visual Studio также может добавить docker-compose.yml файл для всего решения с параметром Add > Container Orchestrator Support.... На шаге 4 мы рассмотрим этот вариант более подробно.

Использование существующего официального образа .NET Docker

Обычно вы создаете пользовательский образ для своего контейнера на основе базового образа, который можно получить из официального репозитория, например через реестр Центра Docker. Именно это происходит на внутреннем уровне при включении поддержки Docker в Visual Studio. Ваш Dockerfile будет использовать существующий образ dotnet/core/aspnet.

Ранее было показано, какие образы и репозитории Docker можно использовать в зависимости от выбранной платформы и операционной системы. Например, если вы выбрали ASP.NET Core (Windows или Linux), следует использовать образ mcr.microsoft.com/dotnet/aspnet:8.0. Таким образом, достаточно просто указать, какой базовый образ Docker будет использоваться для контейнера. Для этого добавьте FROM mcr.microsoft.com/dotnet/aspnet:8.0 в свой Dockerfile. Visual Studio выполнит это автоматически, но в случае обновления версии вы обновляете это значение.

Использование официального репозитория образов .NET из Центра Docker с номером версии гарантирует, что на всех компьютерах (включая компьютеры для разработки, тестирования и работы) будут доступны одни и те же функции языка.

Ниже приведен пример Dockerfile для контейнера ASP.NET Core.

FROM mcr.microsoft.com/dotnet/aspnet:8.0
ARG source
WORKDIR /app
EXPOSE 80
COPY ${source:-obj/Docker/publish} .
ENTRYPOINT ["dotnet", " MySingleContainerWebApp.dll "]

В этом случае образ основан на версии 8.0 официального образа Docker ASP.NET Core (многоархивовый для Linux и Windows). Это параметр FROM mcr.microsoft.com/dotnet/aspnet:8.0. (Дополнительные сведения об этом базовом образе см . на странице ASP.NET Core Docker Image .) В Dockerfile также необходимо указать Docker прослушивать TCP-порт, который будет использоваться во время выполнения (в этом случае порт 80, как настроено с параметром EXPOSE).

В Dockerfile можно задать дополнительные параметры конфигурации, в зависимости от используемого языка и платформы. Например, параметр ENTRYPOINT со значением ["dotnet", "MySingleContainerWebApp.dll"] указывает Docker запускать приложение .NET. Если для создания и запуска приложения .NET используется пакет SDK и .NET CLI (dotnet CLI), этот параметр будет другим. Параметр ENTRYPOINT, который находится в нижней строке, и другие параметры будут отличаться в зависимости от языка и платформы, выбранных для приложения.

Дополнительные ресурсы

Использование мультиархитектурных репозиториев

Один репозиторий может содержать варианты платформ, например образ Linux и образ Windows. Эта функция позволяет поставщикам, таким как Майкрософт, которые создают базовые образы, создать один репозиторий для охвата нескольких платформ (т. е. Windows и Linux). Например, репозиторий .NET в реестре Docker Hub обеспечивает поддержку Linux и Windows Nano Server при использовании одного и того же имени репозитория.

Можно указать тег, явно задающий платформу, как в следующих случаях:

  • mcr.microsoft.com/dotnet/aspnet:8.0-bullseye-slim
    Целевые объекты: только среда выполнения .NET 8 в Linux

  • mcr.microsoft.com/dotnet/aspnet:8.0-nanoserver-ltsc2022
    Целевые объекты: только среда выполнения .NET 8 в Windows Nano Server

Появилась возможность указывать одно и то же имя образа, даже с одинаковым тегом, и новые мультиархитектурные образы (например, образ aspnet) будут использовать версию Windows или Linux в зависимости от развернутой базовой ОС Docker, как показано в следующем примере:

  • mcr.microsoft.com/dotnet/aspnet:8.0
    Многоархивная версия: среда выполнения .NET 8 только в Linux или Windows Nano Server в зависимости от ОС узла Docker

Таким образом, при запросе образа с узла Windows будет получен вариант для Windows, а при запросе образа с тем же именем с узла Linux будет получен вариант для Linux.

Многоэтапная сборка в файле Dockerfile

Dockerfile похож на пакетный сценарий. Он похож на действия в ситуации, если бы вам необходимо было установить что-то на компьютере из командной строки.

Он начинается с базового образа, который задает начальный контекст; это как начальная файловая система, которая надстраивается над базовой ОС. Это не ОС в строгом смысле, но можно представить его как "ОС внутри контейнера".

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

Поскольку каждый новый уровень "накладывается" на предыдущий и итоговый размер образа увеличивается с каждой командой, образы могут становиться очень большими, если они включают, например, пакет SDK для сборки и публикации приложения.

Здесь в дело вступает многоэтапная сборка (в Docker 17.05 и более поздних версий), творя настоящие чудеса.

Основная ее идея в том, что можно разделить процесс выполнения Dockerfile на этапы; каждый этап — исходный образ, за которым следуют команды, а последний этап определяет размер окончательного образа.

Короче говоря, многоэтапная сборка позволяет разделить создание образа на этапы и затем собрать окончательный образ, используя только соответствующие каталоги из промежуточных этапов. Общая стратегия использования этой функции такова:

  1. Использовать базовый образ пакета SDK (его размер не имеет значения), где есть все необходимое для сборки и публикации приложения в папке.

  2. Затем использовать небольшой базовый образ времени выполнения и скопировать папку публикации из предыдущего этапа для создания небольшого окончательного образа.

Возможно, лучший способ понять, как работает многоэтапный процесс, — это пройти в файле Dockerfile по каждой строке; давайте начнем с базового файла Dockerfile, созданного с помощью Visual Studio при добавлении поддержки Docker в проект, чтобы позже внести некоторые оптимизации.

Исходный файл Dockerfile может выглядеть следующим образом:

 1  FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
 2  WORKDIR /app
 3  EXPOSE 80
 4
 5  FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
 6  WORKDIR /src
 7  COPY src/Services/Catalog/Catalog.API/Catalog.API.csproj …
 8  COPY src/BuildingBlocks/HealthChecks/src/Microsoft.AspNetCore.HealthChecks …
 9  COPY src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks …
10  COPY src/BuildingBlocks/EventBus/IntegrationEventLogEF/ …
11  COPY src/BuildingBlocks/EventBus/EventBus/EventBus.csproj …
12  COPY src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj …
13  COPY src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj …
14  COPY src/BuildingBlocks/WebHostCustomization/WebHost.Customization …
15  COPY src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions …
16  COPY src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions …
17  RUN dotnet restore src/Services/Catalog/Catalog.API/Catalog.API.csproj
18  COPY . .
19  WORKDIR /src/src/Services/Catalog/Catalog.API
20  RUN dotnet build Catalog.API.csproj -c Release -o /app
21
22  FROM build AS publish
23  RUN dotnet publish Catalog.API.csproj -c Release -o /app
24
25  FROM base AS final
26  WORKDIR /app
27  COPY --from=publish /app .
28  ENTRYPOINT ["dotnet", "Catalog.API.dll"]

И вот подробности, по одной строке:

  • Строка #1. Начните этап с "небольшого" базового образа среды выполнения, вызовите его для ссылки.

  • Строка 2. Создание каталога /app в образе.

  • Строка 3. Предоставление порта 80.

  • Строка 5. Начало нового этапа с изображением "большой" для создания и публикации. Назовем его build.

  • Строка 6. Создание каталога /src в изображении.

  • Строка 7. До строки 16 скопируйте файлы проекта CSPROJ , чтобы позже восстановить пакеты.

  • Строка 17. Восстановление пакетов для проекта Catalog.API и ссылочных проектов.

  • Строка #18. Скопируйте все дерево каталогов для решения (за исключением файлов и каталогов, включенных в файл DOckerignore ) в каталог /src на изображении.

  • Строка #19. Измените текущую папку на проект Catalog.API .

  • Строка 20. Создание проекта (и других зависимостей проекта) и выходные данные в каталог /app на изображении.

  • Строка 22. Начало нового этапа, продолжающегося из сборки. Назовем его publish.

  • Строка 23. Публикация проекта (и зависимостей) и выходные данные в каталог /app на изображении.

  • Строка 25. Начало нового этапа, продолжающегося с базы , и вызовите его окончательным.

  • Строка 26. Измените текущий каталог на /app.

  • Строка 27. Скопируйте каталог /app с этапа публикации в текущий каталог.

  • Строка 28. Определите команду, выполняемую при запуске контейнера.

Теперь давайте рассмотрим некоторые оптимизации для повышения производительности всего процесса; в случае eShopOnContainers сборка полного решения в контейнерах Linux занимает около 22 минут или более.

Вы используете преимущества многоуровневого кэша Docker, которая не представляет особых сложностей: если базовый образ и команды — такие же, как в некоторых ранее выполненных случаях, можно просто использовать полученный слой без необходимости повторного выполнения команд, что экономит время.

Таким образом, давайте сосредоточимся на этапе build; строки 5–6 практически одинаковы, но строки 7–17 отличаются для каждой службы из eShopOnContainers, поэтому они должны выполняться каждый раз, но если изменить строки 7–16 на следующие:

COPY . .

то они будет практически аналогичны для каждой службы; строка копирует все решение и создаст слой большего размера, но при этом

  1. процесс копирования будет выполняться только в первый раз (и при перестроении в случае изменения файла); для всех других служб будет использоваться кэш.

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

Следующая значительная оптимизация касается команды restore, выполняемой в строке 17; она также отличается для каждой службы eShopOnContainers. Если вы измените эту строку так:

RUN dotnet restore

то она позволит восстановить пакеты для всего решения, что позволяет повторять ее только один раз вместо 15.

Тем не менее dotnet restore запускается, только если в папке есть лишь один файл проекта или решения, поэтому решения этой задачи немного сложнее. Если не вдаваться в подробности, все обстоит так:

  1. Добавьте приведенные ниже строки в .dockerignore:

    • *.sln для игнорирования всех файлов решения в главном дереве папок

    • !eShopOnContainers-ServicesAndWebApps.sln, чтобы включить только этот файл решения.

  2. Включите аргумент /ignoreprojectextensions:.dcproj в dotnet restore, чтобы он также игнорировал проект docker-compose и восстанавливал только пакеты для решения eShopOnContainers-ServicesAndWebApps.

Для окончательной оптимизации отметим, что строка 20 является избыточной, так как строка 23 также собирает приложение и следует, по сути, сразу после строки 20, поэтому можно убрать еще одну времязатратную команду.

Полученный файл будет таким:

 1  FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
 2  WORKDIR /app
 3  EXPOSE 80
 4
 5  FROM mcr.microsoft.com/dotnet/sdk:8.0 AS publish
 6  WORKDIR /src
 7  COPY . .
 8  RUN dotnet restore /ignoreprojectextensions:.dcproj
 9  WORKDIR /src/src/Services/Catalog/Catalog.API
10  RUN dotnet publish Catalog.API.csproj -c Release -o /app
11
12  FROM base AS final
13  WORKDIR /app
14  COPY --from=publish /app .
15  ENTRYPOINT ["dotnet", "Catalog.API.dll"]

Создание базового образа с нуля

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

Дополнительные ресурсы

Image for Step 3.

Шаг 3. Создание пользовательских образов Docker и внедрение в них собственных приложений или служб

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

Обратите внимание, что образы Docker в Visual Studio создаются автоматически. Следующие действия потребуются только в рабочем процессе с использованием редактора/CLI и подробно описываются, чтобы показать, что происходит внутри.

Разработчик должен выполнять разработку и тестирование локально до тех пор, пока не завершит и отправит компонент или пока не перейдет в систему управления версиями (например, в GitHub). Это означает, что необходимо создавать образы Docker и разворачивать контейнеры на локальном узле Docker (на виртуальной машине Windows или Linux), а затем выполнять запуск, тестирование и отладку этих локальных контейнеров.

Чтобы создать пользовательский образ в локальной среде с помощью Docker CLI и Dockerfile, можно использовать команду docker build, как показано на рисунке 5-5.

Screenshot showing the console output of the docker build command.

Рис. 5-5. Создание пользовательского образа Docker

При необходимости вместо непосредственного выполнения команды docker build из папки проекта можно сначала создать развертываемую папку с нужными библиотеками .NET и двоичными файлами, выполнив команду dotnet publish, а затем использовать команду docker build.

Это создаст образ Docker с именем cesardl/netcore-webapi-microservice-docker:first. В данном случае :first — это тег, представляющий конкретную версию. Этот шаг можно повторить для каждого пользовательского образа, который вам требуется создать для своего составного приложения Docker.

Если приложение состоит из нескольких контейнеров (т. е. это многоконтейнерное приложение), можно также использовать команду docker-compose up --build, чтобы собрать все связанные образы одной командой с помощью метаданных, представленных в связанном файле docker-compose.yml.

Вы можете найти существующие в локальном репозитории образы с помощью команды docker images, как показано на рисунке 5-6.

Console output from command docker images, showing existing images.

Рис. 5-6. Просмотр существующих образов с помощью команды docker images

Создание образов Docker с помощью Visual Studio

При использовании Visual Studio для создания проекта с поддержкой Docker не требуется создавать образ явно. Вместо этого изображение создается при нажатии клавиши F5 (или CTRL+F5), чтобы запустить dockerized приложение или службу. Этот шаг выполняется в Visual Studio автоматически, и вы не увидите, как это происходит, но важно знать, что происходит внутри.

Image for the optional Step 4.

Шаг 4. Определение служб в файле docker-compose.yml при сборке многоконтейнерного приложения Docker

В файле docker-compose.yml можно задать ряд связанных служб для развертывания в качестве составного приложения с помощью команд развертывания. Он также настраивает отношения зависимости и конфигурацию среды выполнения.

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

version: '3.4'

services:

  webmvc:
    image: eshop/web
    environment:
      - CatalogUrl=http://catalog-api
      - OrderingUrl=http://ordering-api
    ports:
      - "80:80"
    depends_on:
      - catalog-api
      - ordering-api

  catalog-api:
    image: eshop/catalog-api
    environment:
      - ConnectionString=Server=sqldata;Port=1433;Database=CatalogDB;…
    ports:
      - "81:80"
    depends_on:
      - sqldata

  ordering-api:
    image: eshop/ordering-api
    environment:
      - ConnectionString=Server=sqldata;Database=OrderingDb;…
    ports:
      - "82:80"
    extra_hosts:
      - "CESARDLBOOKVHD:10.0.75.1"
    depends_on:
      - sqldata

  sqldata:
    image: mcr.microsoft.com/mssql/server:latest
    environment:
      - SA_PASSWORD=Pass@word
      - ACCEPT_EULA=Y
    ports:
      - "5433:1433"

Данный файл docker-compose.yml представляет собой упрощенную и объединенную версию. Он содержит статические данные конфигурации для каждого контейнера (такие как имя пользовательского образа), которые требуются всегда, а также сведения о конфигурации, которые могут зависеть от среды развертывания, такие как строка подключения. В следующих разделах вы узнаете, как можно разбить конфигурацию в файле docker-compose.yml на несколько файлов docker-compose и переопределить значения в зависимости от среды и типа выполнения (отладка или выпуск).

В примере файла docker-compose.yml определяются четыре службы: служба webmvc (веб-приложение), две микрослужбы (ordering-api и basket-api) и один контейнер источника данных, sqldata, на основе SQL Server для Linux, работающего как контейнер. Каждая служба развертывается как контейнер, поэтому образ Docker требуется для каждой службы.

Файл docker-compose.yml задает не только используемые контейнеры, но и их индивидуальные конфигурации. Например, в определении контейнера webmvc в файле .yml задается следующее.

  • Использует предварительно созданный образ eshop/web:latest. Однако вы также можете настроить сборку этого образа при выполнении команды docker-compose с дополнительной конфигурацией на основе раздела build: в файле docker-compose.

  • Инициализируются две переменные среды (CatalogUrl и OrderingUrl).

  • Предоставленный порт 80 в контейнере переадресуется на внешний порт 80 на хост-компьютере.

  • Веб-приложение связывается со службами catalog и ordering с помощью параметра depends_on. В результате данная служба будет ожидать запуска этих служб.

Мы вернемся к файлу docker-compose.yml в следующем разделе, когда будем рассматривать реализацию микрослужб и многоконтейнерных приложений.

Работа с файлом docker-compose.yml в Visual Studio 2022

Наряду с возможностью добавления Dockerfile в проект, как уже отмечалось, Visual Studio 2017 версии 15.8 и выше позволяет включить в решении поддержку оркестратора для Docker Compose.

При добавлении поддержки оркестратора контейнеров, как показано на рисунке 5-7, в первый раз Visual Studio создает файл Dockerfile для проекта и создает новый проект (раздел службы) в решении с несколькими глобальными файлами docker-compose*.yml, а затем добавляет проект для таких файлов. Затем можно открыть файлы docker-compose.yml и добавить в них дополнительные возможности.

Повторите эту операцию для каждого проекта, который вы хотите включить в файл docker-compose.yml.

На момент написания этой статьи Visual Studio поддерживает оркестраторы Docker Compose.

Screenshot showing the Container Orchestrator Support option in the project context menu.

Рис. 5-7. Включение поддержки Docker в Visual Studio 2022 щелчком правой кнопки мыши на проекте ASP.NET Core

После добавления поддержки оркестратора в решение в Visual Studio вы также увидите новый узел в обозревателе решений (в файле проекта docker-compose.dcproj), содержащий добавленные файлы docker-compose.yml, как показано на рисунке 5-8.

Screenshot of docker-compose node in Solution Explorer.

Рис. 5-8. Узел дерева docker-compose, добавленный в Обозреватель решений Visual Studio 2022

Можно развернуть многоконтейнерное приложение с единственным файлом docker-compose.yml с помощью команды docker-compose up. Однако Visual Studio добавляет группу этих файлов, чтобы вы могли переопределять значения в зависимости от среды (разработки или рабочей) и типа выполнения (выпуска или отладки). Эта возможность разъясняется в следующих разделах.

Image for the Step 5.

Шаг 5. Сборка и запуск приложения Docker

Если в приложении имеется только один контейнер, его можно запустить путем развертывания на узле Docker (на виртуальной машине или физическом сервере). Но если приложение содержит несколько служб, его можно развернуть как составное приложение с помощью одной команды CLI (docker-compose up)) или в Visual Studio, в котором внутри будет выполняться эта же команда. Давайте рассмотрим разные варианты.

Вариант A. Запуск одноконтейнерного приложения

Использование Docker CLI

Контейнер Docker можно запустить с помощью команды docker run, как показано на рисунке 5-9.

docker run -t -d -p 80:5000 cesardl/netcore-webapi-microservice-docker:first

Приведенная выше команда создает новый экземпляр контейнера из указанного образа при каждом запуске. Можно использовать параметр --name для указания имени контейнера, а затем использовать docker start {name} (также поддерживаются идентификатор контейнера и автоматически присваиваемое имя) для запуска существующего экземпляра контейнера.

Screenshot running a Docker container using the docker run command.

Рис. 5-9. Запуск контейнера Docker с помощью команды docker run

В этом случае команда привязывает внутренний порт 5000 контейнера к порту 80 хост-компьютера. Это означает, что узел выполняет прослушивание порта 80 и переадресацию в порт 5000 в контейнере.

Показанный хэш — это идентификатор контейнера; ему также присваивается случайное доступное для чтения имя, если параметр --name не используется.

Visual Studio

Если вы еще не добавили поддержку оркестратора контейнеров, вы также можете запустить одно приложение контейнера в Visual Studio, нажав клавиши CTRL+F5 , и вы также можете использовать F5 для отладки приложения в контейнере. Контейнер запускается локально с помощью команды docker run.

Вариант Б. Запуск многоконтейнерного приложения

В большинстве корпоративных сценариев приложение Docker будет состоять из нескольких служб; это означает, что необходимо запускать многоконтейнерное приложение, как показано на рисунке 5-10.

VM with several Docker containers

Рис. 5-10. Виртуальная машина с развернутыми контейнерами Docker

Использование Docker CLI

Для запуска многоконтейнерного приложения с помощью Docker CLI используйте команду docker-compose up. Эта команда разворачивает многоконтейнерное приложение с помощью файла docker-compose.yml, существующего на уровне решения. На рисунке 5-11 показаны результаты выполнения этой команды из главного каталога решения, в котором находится файл docker-compose.yml.

Screen view when running the docker-compose up command

Рис. 5-11. Пример результата выполнения команды docker-compose up

После выполнения команды docker-compose up приложение и связанные с ним контейнеры развертываются в узле Docker, как показано на рисунке 5-10.

Visual Studio

Запуск многоконтейнерного приложения с помощью Visual Studio 2019 не может быть проще. Вы просто нажимаете клавиши CTRL+F5, чтобы запустить или F5 для отладки, как обычно, настройка проекта docker-compose в качестве запускаемого проекта. Visual Studio обрабатывает все необходимые настройки, чтобы можно было создать точки останова обычным образом и без особых усилий отлаживать наконец ставшие независимыми процессы, запущенные на "удаленных серверах" с уже подключенным отладчиком.

Как упоминалось ранее, каждый раз при добавлении поддержки решения Docker в проект в решении этот проект настраивается в глобальном (на уровне решения) файле docker-compose.yml, что позволяет запускать или отлаживать все решение сразу. Visual Studio будет запускать по одному контейнеру для каждого проекта с включенной поддержкой решения Docker и выполнять все внутренние шаги автоматически (dotnet publish, docker build и т. д.).

Если вы хотите оценить масштаб этой утомительной работы, взгляните на файл:

{root solution folder}\obj\Docker\docker-compose.vs.debug.g.yml

Здесь важно то, что, как показано на рисунке 5-12, в Visual Studio 2019 имеется дополнительная команда Docker для действия клавиши F5. Эта возможность позволяет запускать или отлаживать многоконтейнерное приложение путем запуска всех контейнеров, определенных в файлах docker-compose.yml на уровне решения. Возможность отладки многоконтейнерных решений означает, что можно установить несколько точек останова, чтобы все они были в разных проектах (контейнерах), и во время отладки из Visual Studio вы будете останавливаться в точках останова, заданных в разных проектах, и работать в разных контейнерах.

Screenshot of the debug toolbar running a docker-compose project.

Рис. 5-12. Запуск многоконтейнерных приложений в Visual Studio 2022

Дополнительные ресурсы

Примечание о тестировании и развертывании с использованием оркестраторов

Команды docker-compose up и docker run (или запуск и отладка контейнеров в Visual Studio) подходят для тестирования контейнеров в вашей среде разработки. Но этот подход не следует использовать для развертывания в рабочей среде, где следует выбирать оркестраторы, например Kubernetes или Service Fabric. При работе с Kubernetes необходимо использовать модули для организации контейнеров и службы для их объединения в сеть. Можно также использовать развертывания для упорядочения создания и изменения модулей.

Image for the Step 6.

Шаг 6. Тестирование приложения Docker с помощью локального узла Docker

Этот шаг будет зависеть от того, что делает ваше приложение. В случае простого веб-приложения .NET, развернутого в виде единственного контейнера или службы, можно получить доступ к этой службе, открыв на узле Docker браузер и перейдя в нем на этот сайт, как показано на рисунке 5-13. (Если конфигурация в Dockerfile сопоставляет контейнер с портом узла, отличным от 80, укажите этот порт узла в URL-адресе.)

Screenshot of the response from localhost/API/values.

Рис. 5-13. Пример локального тестирования приложения Docker с помощью localhost

Если localhost не указывает на IP-адрес узла Docker (при использовании Docker CE это должно происходить по умолчанию), то для перехода к службе используйте IP-адрес сетевой карты вашего компьютера.

Этот URL-адрес в браузере использует порт 80 для рассматриваемого примера конкретного контейнера. Однако внутренние запросы перенаправляются на порт 5000, поскольку именно так было выполнено развертывание с помощью команды docker run, как описано в предыдущем шаге.

Вы также можете тестировать приложение с помощью команды curl с терминала, как показано на рисунке 5-14. В случае установки Docker в Windows по умолчанию всегда будет использоваться IP-адрес узла Docker 10.0.75.1 помимо фактического IP-адреса вашего компьютера.

Console output from getting the http://10.0.75.1/API/values with curl.

Рис. 5-14. Пример локального тестирования приложения Docker с помощью curl

Тестирование и отладка контейнеров в Visual Studio 2022

При запуске и отладке контейнеров в Visual Studio 2022 вы можете отлаживать приложения .NET в основном так же, как при запуске без контейнеров.

Тестирование и отладка без Visual Studio

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

Дополнительные ресурсы

Упрощенный рабочий процесс при разработке контейнеров в Visual Studio

В сущности, при использовании Visual Studio рабочий процесс гораздо проще, чем при использовании редактора или CLI. Большинство шагов, необходимых для Docker и связанных с Dockerfile и docker-compose.yml, выполняются скрыто от пользователя или значительно упрощаются благодаря Visual Studio, как показано на рисунке 5-15.

Diagram showing the five simplified steps it takes to create an app.

Процесс разработки для приложений Docker: 1 — код приложения, 2 — запись Dockerfile/s, 3 — создание образов, определенных в Dockerfile/s, 4 — (необязательно) Создание служб в файле docker-compose.yml, 5 — запуск контейнера или приложения docker-compose, 6 — тестирование приложения или микрослужб, 7 — отправка в репозиторий и повтор.

Рис. 5-15. Упрощенный рабочий процесс при разработке в Visual Studio

Кроме того, вам достаточно будет выполнить шаг 2 (добавление поддержки Docker в проекты) только один раз. Таким образом, рабочий процесс аналогичен другим обычным задачам разработки, когда для разработки используется .NET. Вам нужно знать, что происходит на самом деле (процесс создания образа, какие базовые образы используются, развертывание контейнеров и т. п.), и в некоторых случаях также может потребоваться изменить файл Dockerfile или docker-compose.yml, чтобы настроить функциональность. Но благодаря Visual Studio большую часть работы можно выполнить гораздо проще, что существенно повышает эффективность работы.

Использование команд PowerShell в DockerFile для настройки контейнеров Windows

Контейнеры Windows позволяют преобразовывать существующие приложения Windows в образы Docker и развертывать их с помощью тех же средств, что и остальную часть экосистемы Docker. Чтобы использовать контейнеры Windows, выполните команды PowerShell в Dockerfile, как показано в следующем примере:

FROM mcr.microsoft.com/windows/servercore
LABEL Description="IIS" Vendor="Microsoft" Version="10"
RUN powershell -Command Add-WindowsFeature Web-Server
CMD [ "ping", "localhost", "-t" ]

В этом случае мы используем базовый образ Windows Server Core (параметр FROM) и устанавливаем службы IIS с помощью команды PowerShell (параметр RUN). Аналогичным образом можно также использовать команды PowerShell для настройки дополнительных компонентов, таких как ASP.NET 4.x, .NET Framework 4.6 и другого программного обеспечения Windows. Например, следующая команда в Dockerfile настраивает ASP.NET 4.5:

RUN powershell add-windowsfeature web-asp-net45

Дополнительные ресурсы