Что нужно сделать перед прохождением блока:
- Установить Docker Desktop для своей системы (для Linux необязательно). Для Windows понадобится ещё WSL, но можно делать всё на виртуалке с Linux).
- Зарегистрировать аккаунт на Docker Hub.
- Установить Minikube для своей системы по инструкции. При запуск Minikube можно в качестве драйвера использовать docker (--vm-driver=docker), для этого должен быть запущен Docker Daemon (например, с помощью Docker Desktop).
Классический вопрос с собеседования - в чём разница виртуальной машины и контейнера/Docker? Ответ, как всегда, можно посмотреть на Wiki, нас же интересует, как пользоваться Docker.
Всё начинается с написания Dockerfile. Dockerfile - "инструкция" по сборке образа, из которого будет запускаться контейнер. Образ - готовый и упакованный набор ПО, готовый к развёртыванию.
Образ состоит из слоёв. Слой - команда, результат выполнения которой можно переиспользовать, например, результат команды
RUN dotnet build
. Не всякая команда создаёт слой (вообще, только четыре команды могут это делать: FROM
, RUN
, COPY
, и ADD
).
Все команды можно посмотреть здесь.
У образа может быть базовый образ, с которого начинается сборка (задаётся командой FROM
). Это часто бывает удобно, потому что не нужно заново устанавливать всё ПО, необходимое для работы.
Пример базовых образов - dotnet/aspnet:8.0
и dotnet/sdk:8.0
.
Заметим, что название образа (или, по-другому, тег) чаще всего состоит из названия пользователя/организации, названия самого образа и версии. Версия может задаваться в произвольном формате, но всегда она следует после :
.
Давай попробуем собрать свой образ!
Для начала добавь в репозиторий файл Dockerfile (это стандартное название файла). Работать будем с текущим проектов WebApp. Теперь нужно сделать следующее:
- Добавить базовый образ (адрес - mcr.microsoft.com/dotnet/aspnet:8.0-alpine);
- Выставить наружу порт приложения (обычно 8080);
- restore Nuget-пакетов (тут уже нужен новый базовый образ, да, их может быть несколько, -- mcr.microsoft.com/dotnet/sdk:8.0);
- Билд для проверки того, что приложение билдится;
- Паблиш приложения (в виде exe либо dll, со вторым будет проще выполнять дальнейшие действия);
- выставить приложение в качестве entry-point контейнера.
Для первого используй команду FROM
, для второго - EXPOSE
, для остальных - WORKDIR
, RUN
и, возможно, COPY
. Для последнего пункта - ENTRYPOINT
.
Проверь сборку контейнера командой docker build .
либо запуском файла в Rider. Если нет ошибок, можно двигаться дальше.
После сборки контейнера скопируй id полученного образа (он будет в логах сборки или в Rider), после чего выполни команду
docker run <id_образа>
. Если на предыдущем этапе всё сделано правильно, увидишь логи запуска приложения dotnet.
Если у тебя MacOS, этот пункт выполнить целиком не получится из-за бага в Docker для MacOS, который не даёт полноценно пробрасывать порты между хостом и контейнером.
Останови контейнер и выполни команду docker run <id_образа> -p 50121:8080
. Вместо 50121 может быть произвольный свободный порт в твоей системе.
Если всё ок, по адресу http://localhost:50121/WeatherForecast
откроется результат выполнения запроса к методу API нашего приложения.
Если у тебя MacOS и всё ок, вместо ответа ты увидишь 403 Forbidden (из-за Docker).
Minikube - односерверный вариант Kubernetes. Kubernetes (k8s) - система для автоматического деплоя, скалирования и управления контейнеризированными приложениями. Типовую структуру кластера можно посмотреть здесь. Кратко - приложениями запускаются в так называемых pods (подах) на машинах-узлах (nodes). На одной ноде может располагаться много подов. Контролируется это всё control plane (чаще называемые primary-серверами). Primary может быть несколько, но всегда нечётное количество (для достижения кворума). Minikube же объединяет в себе все компоненты на одной машине.
Для запуска достаточно выполнить команду minikube start
.
k8s оперирует собранными образами. Чтобы он смог взять образ, нужно его куда-нибудь опубликовать. Такие хранилища называются registry. Вариантов несколько:
- локальный registry;
- Docker Hub;
- не публиковать никуда, а шарить docker-демона между хостом и minikube.
Мы пойдём по пути публикации образов в Docker Hub. Для этого:
- Залогинимся командой docker login. При этом введём логин/пароль от учётки, созданной на Docker Hub. Если региистрировались с помощью учётки Google/GitHub, для входа вместо пароля можно использовать токен, который нужно получить в секции Security настроек профиля.
- Добавим тег нашему образу, чтобы было понятнее, что это за образ. Добавляется он командой
docker tag <id_образа> <tag>
и состоит из следующих частей:
- имя профиля на Docker Hub, иначе получишь access denied при пуше;
- название после слэша;
- версия после двоеточия.
Например, myaccount/myimage:myversion 3. Запушим командой docker push .
Проверьте на Docker Hub в профиле после пуша, что образ там отображается.
Одно из ключевых понятий k8s - deployment. Оно включает в себя образ приложения, который будет разворачиваться. Для деплоя нужно создать deployment
командой kubectl create deployment <name> --image=docker.io/<image>
(для случая с Docker Hub, для других registry адрес будет отличаться).
Происходит деплой обычно быстро. Проверить работоспособность деплоймента и подов можно с помощью команд
kubectl get deployments
и kubectl get pods
.
Сервис - способ прокидывания наружу сетевого приложения, которое запущено в кластере k8s. Нас интересует способ через LoadBalancer, который является стандартным для выставления сервиса в "дикую" сеть.
Создать сервис можно с помощью команды kubectl expose deployment <name>--type=LoadBalancer --port=<port>
. С портом можно поэкспериментировать.
Теперь выполняем в отдельном терминале команду minikube tunnel
, чтобы работало связывания сети хоста и k8s. Если всё получилось, можно открыть страницу
http://localhost:/WeatherForecast. Должен появиться JSON с прогнозом погоды от нашего сервиса.