17 KiB
		
	
	
	
			
		
		
	
	Задания
1. Многоступенчатая сборка образов
В полученной вами директории todo_app находятся исходные коды Enterprise Quality™® системы для менеджмента напоминаний.
Она состоит из следующих частей:
TodoApi- API-сервис, на платформе.NET 7.todo_ui- веб-интерфейс к этому сервису, Single-PageJavaScriptприложение(SPA), написанное с использованиемVue.js 3.- API-сервис использует 
PostgreSQLдля хранения данных. 
Необходимо будет контейнеризировать эту систему.
Сервис TodoApi имеет следующие шаги сборки:
- Во-первых, для его сборки необходим образ 
mcr.microsoft.com/dotnet/sdk:7.0 - Далее, из директории, в которой находятся исходные коды сервиса(см. 
todo_app/TodoApi),
нужно сделатьdotnet restore TodoApi.csproj- эта команда скачает зависимости сервиса. - Следующим шагом идет непосредственно сборка сервиса. 
Она производится командойdotnet build TodoApi.csproj -c Release -o <output_directory>,
в которой вместо<output_directory>необходимо подставить имя директории, которое будет
содержать бинарные файлы сервиса, например/app/build - Последняя вещь, которую необходимо сделать - это вызывать команду 
dotnet publish TodoApi.csproj -c Release -o <publish_directory>,
которая опубликует результирующие бинарные файлы, а также зависимости сервиса
в<publish_directory>(например в/app/publish). 
Для запуска процесса сервиса, образ SDK не нужен, достаточно лишь образа, содержащего соответствующий фреймворк 
ASP.NET - в данном случае mcr.microsoft.com/dotnet/aspnet:7.0. 
Запуск осуществляется вызовом исполняемого файла ./TodoApi из директории, которая хранит опубликованные 
бинарные файлы сервиса и его зависимостей.
JavaScript приложение собирается следующим образом:
- Прежде всего, необходим образ 
NodeJS- в данном случае подойдетnode:21. - Далее, из директории, в которой находятся исходные коды приложения(см. 
todo_app/todo_ui),
нужно вызыватьnpm install- это команда скачает зависимости приложения. - После этого, в этой же директории необходимо выполнить команду 
npm run build, в результате чего,
в этой директории появится директорияwwwroot, содержащая файлindex.html,
результирующий код на JS, а также его ресурсы, такие как картинки и файлы стилей(css). 
Для запуска JavaScript приложения NodeJS не нужен, достаточно лишь любого веб-сервера, и в 
нашем случае, в API-сервисе такой имеется(он называется Kestrel).
Для хостинга JS-приложения в API-сервисе, необходимо всего лишь скопировать упомянутую выше директорию 
wwwroot внутрь результирующей директории API-сервиса(которая получается после выполнения dotnet publish ...).
Задачи.
- 
Напишите
Dockerfile, из которого можно было бы создать образ, который отвечал бы следующим требованиям:- Образ должен основываться на образе 
mcr.microsoft.com/dotnet/aspnet:7.0 - Готовое приложение API-сервиса вместе с зависимостями должно находиться в директории 
/app JavaScriptприложение должно находиться в директории/app/wwwroot- При старте контейнера из такого образа, должен запускаться приложение API-сервиса.
 
Документация по многоступенчатой сборке образов находится тут: https://docs.docker.com/build/building/multi-stage/
 - Образ должен основываться на образе 
 - 
Создайте образ из полученного
Dockerfileи назовите егоtodo-bundle - 
Перед запуском самого приложения, необходимо запустить и подготовить
PostgreSQLв сетиtodo.Создайте именованную сеть типа
bridge, в которой будет работать вся система, назовите ееtodo.Создайте том данных, в котором
PostgreSQLбудет хранить БД. Назовите егоtodo_pgdata.Запустите именованный контейнер
todo_postgresиз образаpostgres:16, при этом:- При запуске установите следующие переменные окружения контейнера в значение 
todo:POSTGRES_DB- имя базы данных, к которой будет обращаться API-сервисPOSTGRES_USER- пользователь БД, через которого будет работать сервисPOSTGRES_PASSWORD- пароль для пользователя
 - Установите значение переменной среды 
PGDATAв значение/var/lib/postgresql/data- здесьPostgreSQLбудет хранить данные. - Примонтируйте том данных 
todo_pgdataв качестве директории/var/lib/postgresql/data. - Примонтируйте директорию 
initdbизtodo_appв качестве директории/docker-entrypoint-initdb.dвнутри контейнера.
Там находится скриптinit_db.sql, который используется для инициализации базы данных при первом старте контейнера. 
 - При запуске установите следующие переменные окружения контейнера в значение 
 - 
Запустите контейнер
todo_bundleв сетиtodoиз созданного вами образаtodo-bundle, при этом:- Установите значение переменной среды 
ConnectionStrings__PostgreSQLв контейнере равной
Host=todo_postgres;Port=5432;Database=todo;Username=todo;Password=todo. Можете выбрать другойHostв этой строке, если вы назвали контейнер с PostgreSQL по-другому. Аналогично - и другие параметры. - Пробросьте порт 80 на хост-систему(например на порт 8080). 
API-сервис работает на 80м порту по умолчанию, но это можно изменить, установив значение
переменнойASPNETCORE_URLSнапример вhttp://*:5000- тогда внутри контейнера сервис
будет слушать порт 5000. 
Убедитесь, что приложение работает и доступно на выбранном вами порту на локальной машине.
При возникновении сложностей и необходимости отладки, вы можете также установить значение переменной
ASPNETCORE_ENVIRONMENTвDevelopment- таким образом сервис будет выдавать больше логов. - Установите значение переменной среды 
 - 
Несмотря на то что API-сервис поддерживает хостинг
JavaScriptприложения, в реальном(или скорее, идеальном) мире
никто так не делает. Над интерфейсом и API часто работают разные команды, у них может быть разный график работы,
разное версионирование приложений, и тем более разные репозитарии, и разный подход к разработке.Кроме того, хотя
Kestrel- хороший веб-сервер, все же раздача статических файлов - не основная его специализация.Поэтому, руководствуясь принципом разделения ответственности, вам необходимо разделить контейнеризацию
API-сервиса иJavaScriptприложения.Остановите контейнер
todo_bundle, удалите его и образtodo-bundleМодифицируйте
Dockerfileдля API-сервиса, таким образом, чтобы убрать из него все упоминаниеJavaScriptприложения
и его этапов сборки.Создайте образ
todo-apiна основе нового докер-файла.Напишите конфигурацию
Nginxдля использования его как в качестве обратного прокси для API-сервиса, так и для
раздачи файлов изwwwroot, получаемой после сборкиJavaScriptприложения.
При этом:- Учтите, что все методы API-сервера имеют префикс 
/api - Не забудьте о том, что приложение на 
JSявляетсяSPA, и веб-сервер должен перенаправлять все нераспознанные пути
наindex.html(используйте директивуtry_files) - Содержимое 
wwwrootдолжно лежать в/var/www/todo 
Напишите
DockerfileдляJavaScriptприложения, взяв за основу образnginx.
При сборке образа копируйте написанную вами конфигурацию Nginx в/etc/nginx/nginx.conf,
а результат сборкиJavaScriptприложения в/var/www/todo.Создайте образ
todo-uiиз этого докер-файла - Учтите, что все методы API-сервера имеют префикс 
 - 
Запустите в сети
todoконтейнерtodo_apiиз образаtodo-api, при этом:- Не забудьте про переменную среды 
ConnectionStrings__PostgreSQL. - Убедитесь что контейнер недоступен из внешней сети.
 
Запустите в сети
todoконтейнерtodo_uiиз образаtodo-ui, при этом:- Пробросьте порт контейнера 80(или любой другой, который вы использовали при 
написании конфигурации Nginx) на локальную машину(например, опять же на порт 8080) 
Убедитесь что приложение доступно извне и работает.
 - Не забудьте про переменную среды 
 - 
Платформа
.NET, на самом деле, позволяет собирать приложения, отвязанные от "внешней" предустановленной
среды выполнения.Хотя рекомендованный способ докеризации приложений на
.NET- отталкиваться от образа сmcr.microsoft.com, иногда возникает необходимость именно вself-containedприложениях.Модифицируйте
Dockerfileдляtodo-api, следующим образом:- Поменяйте образ SDK для сборки на 
mcr.microsoft.com/dotnet/sdk:7.0-bullseye-slim - Замените команду публикации приложения на 
dotnet publish TodoApi.csproj --self-contained -r linux-x64 -c Release -o /app/publish
(замените/app/publishна директорию которую использовали вы, если она у вас отличается) - Поменяйте результирующий исходный образ на 
debian:bullseye-slim - В образе 
debian:bullseye-slimне хватаетICU, необходимого для запуска полноценного.NETприложения.
Установитеlibicuв этом образе при сборке:apt-get update && apt-get install libicu67 
Пересоберите образ
todo-api, и перезапустите контейнерtodo_apiна его основе, проверьте что всё работает. - Поменяйте образ SDK для сборки на 
 
2. Политики перезапуска и базовый мониторинг
- 
Запустите
todo_ui,todo_apiиtodo_postgresтак, чтобы они перезапускались при ошибке или же
при перезапуске демона Docker.Перезапустите демон Docker, или же вообще, сделайте перезагрузку машины,
и проверьте что контейнеры запустились при старте Docker. - 
Перезапустите контейнер
todo_postges, так чтобы healthcheck:- Запускался командой 
pg_isready -U todo -d todo - Имел интервал 10 секунд
 - Имел timeout 5 секунд
 - Проверка имела бы до 5 попыток старта в случае неудачи
 - Начиналась бы после 10 секунд после старта контейнера
 
 - Запускался командой 
 
3. Ограничение ресурсов
- 
Перезапустите контейнеры
todo_ui,todo_apiиtodo_postgres, так они имели ограничение по памяти в
300, 500 и 800 мегабайт соответственно. Поэкспериментируйте с ограничениями и посмотрите что выходит,
в случае их превышения. - 
Перезапустите контейнеры
todo_ui,todo_apiиtodo_postgres, так они имели ограничение по ресурсам процессора в
1, 1 и 2 соответственно 
4. Docker Compose
- 
Убедитесь что docker compose установлен, проверьте версию.
 - 
Напишите
docker-compose.ymlдля контейнера на основеbusybox, который бы печаталHello, Worldпри запуске. Запустите. - 
Напишите конфигурацию compose для приложения
cats_app.
Сделайте так, чтобы образcats_appсобирался, если его еще не существует.
Запустите приложение через docker compose, используя эту конфигурацию.
Убедитесь в том, что приложение работает. - 
Напишите конфигурацию compose для вышеописанной системы todo. При этом:
- Добавьте туда как healthcheck, так и ограничения ресурсов описанные выше
 - Сделайте так чтобы контейнер 
todo_apiзависел отtodo_postgres, аtodo_ui- отtodo_api.
Сделайте так, чтобы образыtodo-uiиtodo-apiсобирались, если они еще не существуют.
Запустите систему через docker compose, и убедитесь что все работает. 
 - 
Добавьте контейнер из образа
dpage/pgadmin4:7в compose файл к вышеописанной системе, так чтобы он подключался кPostgreSQL
и позволял смотреть данные приложенияtodo.
При этом установите следующие переменные среды в контейнере в соответствующие значения:PGADMIN_DEFAULT_EMAIL=todo@example.comPGADMIN_DEFAULT_PASSWORD=todoPGADMIN_CONFIG_SERVER_MODE=False