Статья Docker в приложениях asp.net core

mrOkey

mrOkey

Red Team
14.11.2017
621
717
Доброго времени суток, codeby.
Перед тем как продолжить основной цикл статей, я решил рассказать об инструментах, дающих неимоверное ускорение разработки. Начнём мы с Docker.

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

Проблема.
Давайте представим, что нам необходимо разработать приложение. Но мы не знаем, ни где это приложение будет запускаться, ни кто им будет пользоваться.
Другими словами - мы решаем проблему кроссплатформенности. Так как существует огромное, постоянно растущее, множество операционных систем и платформ, мы должны предвидеть все варианты. Альтернативное решение - можно скомпилировать приложение под наиболее популярные платформы. Хмм, да, но это очень объемная и вовсе не тривиальная задача.
Более адекватное решение - это разрабатывать под одну систему, систему которую мы можем виртуализировать. И да, до появления docker многие так и решали проблему, но такие приложения получались достаточно громоздкими и ресурсоемкими, разумеется мы этого не понимали пока не появился docker.

Так что же такое Docker
Docker это технология, которая позволяет нам создавать контейнеры ( песочницы ) для упрощения деплоя, развертки и запуска наших приложений на хостовых системах, например на Linux’ах.
Тут вы могли бы подумать, что Docker и виртуальные машины - это одно и тоже, но это не так. Давайте разбираться вместе, первым делом определим понятие виртуализация следующим образом: физически существует один компьютер, выполняющий функции нескольких. Данное поведение достигается за счёт специального программного обеспечения, называемого гипервизором. Гипервизор позволяет разделять ресурсы одного физического компьютера между многими “виртуальными”. Вот так по-детски просто мы описали это понятие.
Докер решают ту же задачу, но другим путём, более эффективным. Рассмотрим картинку ( с офф сайта docker )
Docker в приложениях asp.net core


Хорошо можно заметить, насколько эффективнее работает докер.

Docker для windows.
Поставить docker на Linux не составит проблем, винда же как всегда “преуспела” в этом плане. Чтобы запустить docker под окнами нужно скачать Docker Toolbox. Обычный docker под windows создает много проблем ( в частности забирает возможность пользоваться virtual box ). Скачиваем и ставим. Ничего сложного быть не должно.

Что такое ASP.NET Core
Это логичный виток эволюции, microsoftовского ASP.NET MVC - фреймворка для разработки web-приложений. Наконец-то мелкомягкие сделали кроссплатформенный фреймворк с открытым исходным кодом. Видать, не за горами, светлое будущее.
Думаю нет особого смысла расписывать что это, чем это лучше - поэтому просто отправлю вас читать документацию по этой замечательной вещи.

Необходимое отступление
Конечно рассматривая docker, нужно разрабатывать приложение. Наиболее классно - docker смотрится в микросервисной архитектуре, поэтому мы будем её использовать.
Что у нас будет:
  • Микросервис конвертации валют
  • Микросервис погоды
  • Фронтенд, который будет показывать два виджета - погоду и курс рубля к доллару.
Сервисы выбраны максимально теоретически - основная цель статьи показать красоту docker’а при разработке под asp.net core.

Начнём с микросервиса конвертации валюты. Возьмём уже известный ( по моим другим статьям) клиент для апи. Необходимые данные для конвертации будем брать отсюда: . Первым делом на нужно зарегистрироваться чтобы получить API ключ, для использования апи.
После регистрации на сервисе нам предоставят ключик и дадут url endpoint, куда в дальнейшем мы будем слать запросы. Интересовать нас будет вот этот эндпоин


Переходим к коду. Создаем проект ASP.NET Core.
Определим структуру проекта. Хорошей практикой при разработки апи является его версионирование. Поэтому создадим папку с названием V1, что соответствует нашей версии. Также создадим папку Contracts, где будем хранить модель данных. Затем создадим библиотеку классов (dll) для описания бизнес правил. В нашем случае тут будет размещен апи клиент для сайта .
После этого структура выглядит примерно так:
Docker в приложениях asp.net core


Далее всё просто, как всегда обращаемся к апи сайта, получаем результат. Должен предупредить, что бесплатный план накладывает множество ограничений, например нельзя менять source currencie, но не будем по этому поводу огорчаться.
Docker в приложениях asp.net core

На этом закончим с микросервисом для валюты, не забываем, что микросервисы намеренно выбраны элементарными - цель статьи показать как использовать docker.

Далее создадим микрослужбу для прогноза погоды. В этом нам поможет api, предоставляемое сайтом openweathermap.org. Нам так же необходимо получить API ключ, для этого нужно зарегистрироваться. И так же наш бесплатный аккаунт ограничивают. После регистрации на почту падает ключик.
Нас интересует вот этот endpoint:

Я буду наблюдать зависимость для Новосибирска, параметр units определяет единицы измерения температуры, значение metric - соответствует цельсию.
Аналогично создаем сервис и апи клиент. После нехитрых преобразований выглядеть у нас должно так.
Docker в приложениях asp.net core

и код контроллера
Docker в приложениях asp.net core


В данном случае, мы урезаем результирующий объект. Нам достаточно текущей температуры и названия города.
Прежде чем занятся фронтэнд частью, я хочу немного поэкспериментировать со структурой проекта. Разложить отдельные микросервисы по папкам. Навести порядок так сказать. Теперь всё выглядит вот так.
Docker в приложениях asp.net core

На самом деле уже на этом этапе можно создавать докер контейнеры, но давайте ещё немного наведём порядок, а именно избавимся от хардкода ключей, url’ов и так далее.

Начнём с CurrencyConvert. Уберём апи ключ, и baseurl в файл настроек. Кстати, защита апи ключей в asp.net приложениях целая отдельная тема, которую я раскрою в другой статье. Кроме того, используем принцип DI и воспользуемся новым microsoft’овским DI-контейнером.
Первым делом вынесем url и api key. Для этого в файле appsettings.json создадим секцию Urls и добавим туда данные следующим образом:
Docker в приложениях asp.net core

Ключи я в конце поменял, так что особого профита скрывать их - нет.
Теперь настроим DI контейнер, для этого создадим интерфейс IApiClient следующим образом:
Docker в приложениях asp.net core

Теперь порефакторим старый класс клиента, после преобразований он имеет следующий вид:
Docker в приложениях asp.net core

На 11 строке определяется стратегия повторения запроса запроса к апи, в данном случае это реализовано с помощью библиотеки Polly, используется экспоненциальное повторение. Далее объявляются два приватных поля для url и api ключа соответственно. На строках 21-25 объявлен конструктор класса с параметром. Именно для этого конструктора мы позднее настроим DI. 23 и 24 строки демонстрируют извлечение данных из файла appsettings.json. Далее идёт реализация http метода get средствами стандартного HttpClient’a.

Теперь настроим DI контейнер. Для этого напишем метод расширения для интерфейса IServiceCollection ( который представляет microsoft DI framework ). В нём мы опишем конкретную реализацию интерфейса IApiClient. Выглядеть данный метод будет так.
Docker в приложениях asp.net core

Теперь перейдём в класс Startup.cs проекта CurrencyConvert.WebApi. И изменим метод ConfigureServices. Благодаря нашему методу расширения, мы можем сделать так:
Docker в приложениях asp.net core

Осталось только порефакторить контролер.
После преобразований он выглядит следующим образом:
Docker в приложениях asp.net core

На 13 строке объявляется апи клиент, именно сюда DI-контейнер будет “подсовывать” нужную реализацию данного интерфейса.
Далее всё осталось как было, за исключением преобразования возвращаемого объекта. Теперь там тоже обрезается не нужная информация. Если ты один из тех кто не знает, что такое принцип DI, DI-контейнер, не расстраивайся, а читаю мою другую статью и просвещайся.
Аналогично поступаем с сервисом WeatherInformation.

Для фронтэнда я хочу использовать typescript, react, redux для управления состоянием, axios для запросов к апи, less для разработки стилей. Помимо этого, я буду использовать апи gateway (в виде сервиса на asp net core) Как засетапить и настроить всю эту прелесть я рассказываю тут.

Контейнеризируй всё.
Перед тем как занятся фронтэнд частью я перейду к основной теме статьи - docker контейнеризации.
Первое, что необходимо - это поставить Docker Toolbox. По невнятным причинам Docker for windows не работает на 90% систем. К тому же он просит Hyper-v для своей работы. А Hyper-V убивает oracle virtual box, как известно. Поэтому DockerToolbox - бро, Docker for windows - не бро.
Затем нам необходимо скачать образы microsoft net core. Конкретно нужно скачать:
Код:
microsoft/dotnet:2.1-sdk
microsoft/dotnet:2.1-aspnetcore-runtime
Микрософт, оптимизировала свой образ и образ runtime содержит только необходимый минимум. Кстати, контейнеры на нём получаются порядка 290 мб.
Чтобы загрузить образы, необходимо выполнить следующие команды в терминале
Код:
docker pull microsoft/dotnet:2.1-sdk
docker pull microsoft/dotnet:2.1-aspnetcore-runtime
Итак продолжим, создадим Dockerfile в корневой папке солюшена - это то место где лежат файлы *.sln. Для WeatherInformation (да и для большинства asp net core приложений) - docker файл выглядит так

Хочу сразу сказать, что это оптимизированный образ, по сути, мы создаем тут 2 образа: один который base (я буду назвать его base-runtime) будем запускать, публиковать и так далее, а второй, который build ( он же publish ) удалим, так как он будет весить 1.75GB или около того.
Docker в приложениях asp.net core

На 1-3 строке происходит создание того самого base-runtime слоя. В нём создаётся рабочая директория app и открывается 80-ый порт.
Далее создается build слой и устанавливается рабочая директория - src. Теперь мы должны перенести в контейнер все зависимости, это делается на строках 7-10. Под зависимостями я также подразумеваю установку nuget пакетов. Далее, на строка 12-15 мы билдим и готовим к публикации проект. С 17 строке начинается та самая оптимизация: мы берём результаты команды dotnet publish и копируем их из build слоя в base-runtime слой. Ну и 20ой, завершающей строкой - указываем докеру - какую команду он должен выполнить когда мы запустим контейнер.
Сохраняем файл, и открываем терминал. Теперь нам нужно собрать наш образ. Для этого используем команду docker build. Находясь (в терминале) в папке с Dockerfile’ом выполним следующую команду:
Docker в приложениях asp.net core

параметр -t говорит о том как будет называться образ, и указывать на его версию
В результате вы увидите нечто похожее.
Docker в приложениях asp.net core

Тут видно как докер создает ваш образ шаг за шагом. Наконец, чтоб запустить сие чудо нужно воспользоваться командой docker run. Я не вижу особого смысла описывать известные команды docker, так что почитайте о них в документации.
Команда для запуска контейнера выглядит так:
Docker в приложениях asp.net core

Как вы узнаете из документации параметр -d указывает на то, что контейнер нужно запустить в фоновом режиме, параметр порт указывает какой порт прокинуть наружу, а далее следует наименование образа и версия, которую мы запускаем.
Теперь проверим, что docker run запустил контейнер и всё хорошо. Для этого пропишем docker ps
Docker в приложениях asp.net core

как видим всё хорошо - контейнеры работают.
Чтобы узнать ip назначенный докер машине можно в терминале прописать docker-machine ip
Команда вернет IP адрес докер машины. Так чтобы обратится к контейнеру созданным на основе образа weather, необходимо обратится к 63573 порту, ip адреса docker-machine ip.
Аналогично поступаем с currency микросервисом. Запускаем контейнеры и переходим к фронтенд разработке.
Перед тем как перейти к разработке компонентов, создадим немного инфраструктурного кода (это такой код, который не решает бизнес задач, но без него нельзя обойтись). Нам нужно написать провайдер, для доступа url сервисов. Поскольку в ApiGetewaу у нас имеется файл appsettings.json, где мы храним эти urlы создадим провайдер для него. В папке src/ создаём файл appSettingsProvider.ts и подключаем json файл.
Docker в приложениях asp.net core

Далее нам нужно объявить интерфейс для доступа к сервисам, который повторяет структуру appsettings.json файла.
Docker в приложениях asp.net core

и теперь отдадим объект с настройками клиентскому коду, например так:

Docker в приложениях asp.net core


Теперь везде где необходимо, мы просто подключаем наш провайдер:
Docker в приложениях asp.net core

и используем его
Docker в приложениях asp.net core

Воспользуясь структурой из статьи про установку фронтенд стэка, начнём создавать виджет погоды.
  1. Создаём константы.
    Docker в приложениях asp.net core
  2. Создаём интерфейс для данных
    Docker в приложениях asp.net core
  3. Создаём ActionCreator
    Docker в приложениях asp.net core
  4. Создаём редьюсер
    Docker в приложениях asp.net core
  5. Добавляем редьюсер в корневой редьюсер
    Docker в приложениях asp.net core

  6. Создаем компонент
    Docker в приложениях asp.net core
  7. И подключаем его к хранилищу
    Docker в приложениях asp.net core

Как видите получился довольно четкий алгоритм действий, как я и обещал. Если вы не знакомы с reactом, возможно мне стоит написать и о нём тоже. Поделитесь желанием в комментариях.
Немного поверстав, получаем два виджета выглядит финал версия как-то так ( слишком просто чтобы делать на react & redux ):

Docker в приложениях asp.net core


Docker compose
У нас получилось 3 сервиса:
  • Сервис погоды
  • Сервис курса валют
  • Фронтенд сервис
Разумеется запускать всё через docker run не кошерно. Нужно как менеджить всю нащу docker-сеть. Стандартное средство для этого - docker compose. Он основан на yml файле, в котором описываются все настройки микросервисов. По сути, это удобочитаемый файл конфигурации команды docker run. Итак начнём создавать docker-compose файл.
Docker в приложениях asp.net core


вот и вся хитрость. В свойство build мы указываем путь к Dockerfile. Предполагается, что docker-compose.yml лежит в самом верху иерархии. Свойство ports говорит само за себя. Сервис с фронтендом - добавьте сами.
Теперь прежде чем запустить оркестрацию - необходимо собрать всё это дело. Делается это командой docker-compose build ( находясь в папке с docker-compose файлом ).
После билда, достаточно выполнить docker-compose up чтобы запустить настроенные сервисы.

Docker в приложениях asp.net core

А на этом у меня всё.
ссылка на репозиторий:
 
Последнее редактирование:
C

cherubot

Happy New Year
08.11.2017
39
19
УУУУУх, годнота. В закладки.
 
Мы в соцсетях:  ТелеграмВконтактеДзенФейсбукТвиттерЮтуб