Контейнеризация приложения .NET Core

C Sharp > Контейнеризация приложения .NET Core
26.01.2019 22:35:10



Статья:

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

В ходе работы с этим руководством вы:

  • как создать Dockerfile;
  • как создать приложение .NET Core;
  • как развертывать приложение в контейнер Docker.

.NET Core: самый простой способ начать работу

Перед созданием образа Docker вам потребуется приложение для упаковки в контейнер. Его можно создать в Windows, Linux или MacOS. Самый быстрый и простой способ — использовать .NET Core.

Если вы не знакомы с набором средств CLI .NET Core, прочитайте обзор пакета SDK для .NET Core.

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

Ваше первое приложение Docker для .NET Core

Предварительные требования

Для работы с этим руководством вам понадобится следующее:

Пакет SDK для .NET Core

См. полный список операционных систем, поддерживаемых .NET Core 2.1.x, неподдерживаемых версий ОС, а также ссылки на политики жизненного цикла.

  • Установите любой привычный для вас редактор кода, если еще не сделали этого.

 Совет

Нужно ли устанавливать редактор кода? Попробуйте Visual Studio Code!

Установка клиента Docker

Установите клиент Docker 18.06 или более поздней версии.

Клиент Docker можно установить в:

Создание консольного приложения .NET Core 2.1 для добавления в Docker

Откройте командную строку и создайте папку с именем Hello. Перейдите в созданную папку и введите следующие команды:

console
dotnet new console
dotnet run

Вкратце рассмотрим эти команды.

  1. $ dotnet new console

    dotnet new создает актуальный файл проекта Hello.csproj с зависимостями, необходимыми для создания консольного приложения. Эта команда также создает Program.cs — простой файл, содержащий точку входа для приложения.

    Hello.csproj:

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

    • Тег OutputType указывает, что мы создаем исполняемый файл — другими словами, консольное приложение.
    • Тег TargetFramework указывает, какая реализация.NET является целевой. В расширенном сценарии обработки можно указать несколько целевых платформ и выполнить сборку в них за одну операцию. В этом руководстве описано, как выполнить сборку для .NET Core 2.1.

    Program.cs:

    Программа начинается с команды using System. Это означает "добавить все данные пространства имен System в область видимости для этого файла".Пространство имен System содержит основные конструкции, такие как string, или числовые типы.

    Затем мы определяем пространство имен с именем Hello. Вы можете сменить это пространство имен на любое другое. Класс Program определяется в этом пространстве имен с использованием метода Main, который принимает массив строк в качестве аргумента. Этот массив содержит список аргументов, передаваемых при вызове скомпилированной программы. В нашем примере программа просто выводит "Hello World!" в консоль.

    Dotnet new запускает команду dotnet restore. Dotnet restore восстанавливает дерево зависимостей с помощью вызова NuGet (диспетчер пакетов .NET). NuGet выполняет следующие задачи:

    • анализирует файл Hello.csproj;
    • скачивает файл зависимостей (или получает его из кэша компьютера);
    • записывает файл obj/project.assets.json.

    Файл project.assets.json содержит полную схему зависимостей NuGet, разрешения привязок и другие метаданные приложения. Этот обязательный файл используется другими средствами, например dotnet build и dotnet run, для правильной обработки исходного кода.

  2. $ dotnet run

    dotnet run вызывает dotnet build для подтверждения успешной сборки, а затем dotnet <assembly.dll> для запуска приложения.

    console
    $ dotnet run
    
    Hello World!
    

    Сведения о более сложных сценариях см. в статье Развертывание приложений .NET Core.

Добавление приложения .NET Core в Docker

Консольное приложение Hello .NET Core успешно выполняется локально. Теперь продвинемся на шаг вперед, чтобы собрать и запустить приложение в Docker.

Ваш первый Dockerfile

Для начала работы откройте текстовый редактор. Мы все еще работаем из каталога Hello, где создали приложение.

Добавьте в новый файл приведенные ниже инструкции Docker для контейнеров Windows или Linux. По завершении сохраните его в корне каталога Hello в виде Dockerfile без разрешения (вам может потребоваться задать тип файла All types (*.*)или другой аналогичный).

Dockerfile
FROM microsoft/dotnet:2.1-sdk
WORKDIR /app

# copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore

# copy and build everything else
COPY . ./
RUN dotnet publish -c Release -o out
ENTRYPOINT ["dotnet", "out/Hello.dll"]

Dockerfile содержит инструкции сборки Docker, выполняемые последовательно.

Первой инструкцией должна быть FROM. Она инициализирует новый этап сборки и задает базовый образ для остальных инструкций. Теги мультиархитектурности запрашивают контейнеры Windows или Linux в зависимости от режима контейнеровDocker для Windows. Базовым образом для нашего примера является пакет 2.1-sdk из репозитория microsoft/dotnet.

Dockerfile
FROM microsoft/dotnet:2.1-sdk

Инструкция WORKDIR задает рабочий каталог для всех оставшихся инструкций RUN, CMD, ENTRYPOINT, COPY и ADD в Dockerfile. Если этот каталог не существует, он создается. В этом случае WORKDIR задает каталог приложения.

Dockerfile
WORKDIR /app

Инструкция COPY копирует новые файлы или каталоги из исходного пути и добавляет их в файловую систему конечного контейнера. С этой инструкции мы копируем файл проекта C# в контейнер.

Dockerfile
COPY *.csproj ./

Инструкция RUN выполняет все команды в новом слое поверх текущего образа и фиксирует результаты. Полученный зафиксированный образ используется на следующем шаге в Dockerfile. Мы запускаем dotnet restore, чтобы получить нужные зависимости файла проекта C#.

Dockerfile
RUN dotnet restore

Инструкция COPY копирует остальные файлы в контейнер на новые слои.

Dockerfile
COPY . ./

Мы публикуем приложение с помощью этой инструкции RUN. Команда dotnet publishкомпилирует приложение, считывает его зависимости, указанные в файле проекта, и публикует итоговый набор файлов в каталоге. Наше приложение публикуется с конфигурацией выпуска и выводит данные в каталог по умолчанию.

Dockerfile
RUN dotnet publish -c Release -o out

Инструкция ENTRYPOINT предоставляет возможность запускать контейнер как исполняемый файл.

Dockerfile
ENTRYPOINT ["dotnet", "out/Hello.dll"]

Теперь у вас есть Dockerfile, который:

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

Сборка и запуск приложения Hello .NET Core

Основные команды Docker

Ниже указаны основные команды Docker:

Сборка и запуск

Вы написали Dockerfile, теперь Docker создает приложение и затем запускает контейнер.

console
docker build -t dotnetapp-dev .
docker run --rm dotnetapp-dev Hello from Docker

Выходные данные команды docker build должны быть аналогичны приведенным далее выходным данным консоли:

console
Sending build context to Docker daemon   173.1kB
Step 1/7 : FROM microsoft/dotnet:2.1-sdk
 ---> 288f8c45f7c2
Step 2/7 : WORKDIR /app
 ---> Using cache
 ---> 9af1fbdc7972
Step 3/7 : COPY *.csproj ./
 ---> Using cache
 ---> 86c8c332d4b3
Step 4/7 : RUN dotnet restore
 ---> Using cache
 ---> 86fcd7dd0ea4
Step 5/7 : COPY . ./
 ---> Using cache
 ---> 6faf0a53607f
Step 6/7 : RUN dotnet publish -c Release -o out
 ---> Using cache
 ---> f972328318c8
Step 7/7 : ENTRYPOINT dotnet out/Hello.dll
 ---> Using cache
 ---> 53c337887e18
Successfully built 46db075bd98d
Successfully tagged dotnetapp-dev:latest

Как видно из выходных данных, подсистема Docker использует Dockerfile для создания контейнера.

Выходные данные команды docker run должны быть аналогичны приведенным далее выходным данным консоли:

console
Hello World!

Официальные .NET-образы Docker — это образы Docker, оптимизированные Майкрософт. Они доступны для всех в репозиториях Майкрософт в Центре Docker.Каждый репозиторий может содержать несколько образов, в зависимости от версии платформы .NET и операционной системы (Linux Debian, Linux Alpine, Windows Nano Server, Windows Server Core и т. д.).

Начиная с версии .NET Core 2.1, все образы .NET Core, в том числе для ASP.NET Core, можно найти в репозитории образов .NET Core на сайте Docker Hub: https://hub.docker.com/r/microsoft/dotnet/

Большинство репозиториев образов предоставляют широкие возможности по использованию тегов, чтобы облегчить выбор не только конкретной версии платформы, но и ОС (дистрибутива Linux или версии Windows).

Оптимизация образов .NET Core и Docker для разработки и производства

При создании образов Docker для разработчиков Майкрософт сосредотачивается на следующих основных сценариях:

  • образы, используемые для разработки и сборки приложений .NET Core;

  • образы, используемые для выполнения приложений .NET Core.

Зачем использовать несколько образов? При разработке, сборке и выполнении приложений в контейнерах приоритеты будут разными. Предоставляя различные образы для каждой из задач, Майкрософт помогает оптимизировать отдельные процессы разработки, сборки и развертывания приложений.

Во время разработки и сборки

Во время разработки важна скорость выполнения итераций для изменений и возможность отлаживать изменения. Размер образа не так важен, как возможность быстро вносить изменения в код и просматривать их. Некоторые средства и "контейнеры агентов сборки" на стадии разработки и сборки используют образ .NET Core для разработки (microsoft/dotnet:2.1-sdk). При сборке внутри контейнера Docker надо учитывать, какие элементы необходимы для компиляции приложения. Сюда входят зависимости компилятора и другие зависимости .NET.

Почему так важен этот тип образа сборки? Этот образ не развертывается в рабочую среду. Это образ, который вы используете для сборки содержимого, помещаемого в рабочий образ. Если вы используете многоэтапную сборку Docker, этот образ будет применяться в среде непрерывной интеграции (CI) или в среде сборки.

Производство

При производстве важно быстро развернуть и запустить контейнеры на основе рабочего образа .NET Core. Поэтому образ только для среды выполнения на базе microsoft/dotnet:2.1-aspnetcore-runtime имеет малый размер и может быстро перемещаться по сети из реестра Docker к узлам Docker. Содержимое готово к запуску, поэтому период времени от запуска контейнера до обработки результатов минимален.В модели Docker не нужна компиляция кода C#, поскольку вы выполняете команду dotnet build или dotnet publish при использовании контейнера сборки.

В этот оптимизированный образ вы помещаете только двоичные файлы и другое содержимое, необходимое для выполнения приложения. Например, в содержимое, создаваемое командой dotnet publish, входят только скомпилированные двоичные файлы .NET, образы, файлы .js и .css. Со временем появятся образы, которые содержат пакеты, предварительно скомпилированные JIT-компилятором (компиляция из промежуточного языка в машинный код во время выполнения).

Хотя существует несколько версий образов .NET Core и ASP.NET Core, они все имеют один или несколько общих уровней, включая базовый уровень. Поэтому образ занимает мало места на диске, ведь он содержит лишь различия между вашим образом и базовым образом. В результате можно быстро извлекать образы из реестра.

При просмотре репозиториев .NET-образов в центре Docker вы найдете несколько версий, классифицированных или помеченных тегами. Эти теги помогают определить, какую версию использовать, как показано в таблице:

Изображение Комментарии
microsoft/dotnet:2.1-aspnetcore-runtime ASP.NET Core только со средой выполнения и оптимизацией ASP.NET Core в Linux и Windows (для разных архитектур)
microsoft/dotnet:2.1-sdk

Благодаря модульности и упрощенному характеру .NET Core идеально подходит для контейнеров. При развертывании и запуске контейнера размер его образа гораздо меньше в среде .NET Core. Напротив, при использовании .NET Framework для контейнера необходимо использовать Windows Server Core в качестве базового образа, который занимает гораздо больше места, чем образ Nano Windows Server или Linux, которые используются для .NET Core.

Кроме того, платформа .NET Core является кроссплатформенной, поэтому вы можете разворачивать серверные приложения в Linux и Windows контейнерах. Однако при использовании традиционной .NET Framework можно развернуть только образ, основанный на Windows Server Core.

Ниже более подробно описаны преимущества .NET Core.

Разработка и развертывание на различных платформах

Очевидно, что если ваша цель — приложение (веб-приложение или служба), которое можно запускать на нескольких платформах, поддерживаемых в Docker (Linux и Windows), целесообразно выбрать .NET Core, так как платформа .NET Framework поддерживает только Windows.

.NET Core также поддерживает macOS в качестве платформы разработки. Тем не менее при развертывании контейнеров на узле Docker этот узел должен (в настоящее время) базироваться на Windows или Linux. Например, в среде разработки можно использовать виртуальную машину с Linux, запущенную на компьютере с Mac.

Visual Studio предоставляет интегрированную среду разработки (IDE) для Windows и поддерживает разработку с использованием Docker.

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

Можно также использовать редактор Visual Studio Code (VS Code) на платформах macOS, Linux и Windows. VS Code поддерживает .NET Core, включая технологию IntelliSense и отладку. Поскольку VS Code является упрощенным редактором, то для разработки контейнерных приложений на компьютере Mac его можно использовать в сочетании с Docker CLI и .NET Core CLI. Для разработки на платформе .NET Core также можно использовать большинство сторонних редакторов, например Sublime, Emacs, vi и проект с открытым кодом OmniSharp, который также поддерживает технологию IntelliSense.

Помимо интегрированных сред разработки и редакторов для всех поддерживаемых платформ можно использовать средства .NET Core CLI.

Использование контейнеров для новых ("с нуля") проектов

Контейнеры обычно используются в сочетании с архитектурой микрослужб, хотя их также можно использовать для упаковки веб-приложений или служб, созданных на базе любого архитектурного шаблона. Среду .NET Framework можно использовать для контейнеров Windows, но упрощенный характер и модульный принцип среды .NET Core делают ее оптимальной для контейнеров и архитектуры микрослужб. При создании и развертывании контейнера размер его образа гораздо меньше в среде .NET Core, чем в .NET Framework.

Создание и развертывание микрослужб в контейнерах

Традиционный .NET Framework можно использовать для создания приложений на основе микрослужб (без контейнеров) с помощью простых процессов. Платформа .NET Framework уже установлена и совместно используется процессами, поэтому в этом случае процессы небольшие по размеру и быстро выполняются. Но при использовании контейнеров образы для традиционного .NET Framework основаны на Windows Server Core, что делает их слишком большими для подхода "микрослужбы в контейнерах".

В противоположность этому .NET Core благодаря упрощенному характеру является наилучшим выбором, если вы используете ориентированную на микрослужбы систему, которая основана на контейнерах. Кроме того, связанные с NET Core образы, как Linux, так и Windows Nano, являются компактными и небольшими по размеру, что обеспечивает их быстрый запуск.

Термин "микрослужба" означает, что она должна быть настолько маленькой, насколько это возможно, чтобы обеспечивать быстрое развертывание, занимать мало места в памяти (см. статью о проблемно-ориентированном проектировании), решать небольшую часть задачи и быть способной к быстрому запуску и остановке. Для выполнения этих требований необходимо использовать небольшой и быстро создаваемый образ контейнера, такой как образ контейнера .NET Core.

Архитектура микрослужб также позволяет использовать сочетание технологий за пределами службы. Благодаря этому возможна постепенная миграция на технологию .NET Core новых служб, которые работают совместно с другими микрослужбами или со службами, разработанными с помощью Node.js, Python, Java, GoLang и других технологий.

Развертывание с высокой плотностью в масштабируемых системах

Если для вашей системы, основанной на контейнерах, требуется максимально возможная плотность, детализация и производительность, то мы рекомендуем использовать .NET Core и ASP.NET Core. Среда ASP.NET Core в 10 раз быстрее, чем ASP.NET в традиционном .NET Framework, и поддерживает другие популярные отраслевые технологии микрослужб, такие как сервлеты Java, Go и Node.js.

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