WeatherForecast. Виртуальная машина. Docker.
Предисловие
Замечательно, когда у вашего любимого провайдера есть готовые образы виртуальных машин с установленными docker-ом и docker compose-ом. Но если нет, то ничего страшного. Docker устанавливается по инструкции с официального сайта (сразу даю ссылочку на вариант установки из репозитория "Install using the apt repository"):
https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository
Заводите виртуальную машину (описание тут), только выберите конфигурацию "пожирнее", я для теста взял 2 vCPU, 4RAM, 15 ГБ HDD. Настраивайте подключение по ssh и устанавливайте docker, опыта копирования команд из инструкции вам должно хватить.
И так виртуальная машина готова. Docker установлен.
Поехали
Начнем с решения проблем. Если вы успешно установили docker под root-ом и потом создали своего пользователя, настроили ssh и подключились к виртуальной машине (как это сделал я), то использованием docker-а возникнут проблемы:
Для решения нам нужно добавить своего пользователя в группу "docker". Кстати посмотреть список всех групп в системе можно командой:
cat /etc/group
А проверить список групп, в которые входит ваш пользователь:
groups
Добавляемся в группу "docker" командой:
sudo usermod -aG docker ${USER}
Для того, чтобы изменения применились, нужно разлогиниться и залогиниться, после проверяем:
Работает. Теперь логинимся в наш Container Registry командой:
docker login cr.selcloud.ru
Для проверки скачаем образ нашего приложения и утилиты:
docker pull cr.selcloud.ru/deploy2production/weather-forecast-app-img:v2.0
docker pull cr.selcloud.ru/deploy2production/weather-forecast-setup-img:v2.0
УПС
Посыплю голову пеплом. В пролом посте я накосячил с копированием команд, и собрал один и тот же образ под разными именами (хотя в тексте поста все корректно), и "залил" так в Container Registry. Будь я зорким как орел, я бы заметил одинаковый хэш образов. Но нет. Поэтому я пересобрал опубликовал образы с новым тегом-версией v2.0. Учимся на ошибках - дважды проверяем, хэши нам в помощь.
Продолжим. Давайте для разминки запустим наше приложение в "dev" варианте, как мы это делаем локально, с базами данных в контейнерах.
mkdir dev cd dev nano ./docker-compose.yml
Нам понадобится docker-compose файл с некоторыми изменениями:
name: "weather-forecast" networks: weather-forecast-net: services: postgres: image: "postgres" container_name: "weather-forecast-postgres" networks: - weather-forecast-net ports: - "5432:5432" environment: POSTGRES_PASSWORD: postgres redis: image: "redis" container_name: "weather-forecast-redis" networks: - weather-forecast-net ports: - "6379:6379" app: image: "cr.selcloud.ru/deploy2production/weather-forecast-app-img:v2.0" container_name: "weather-forecast-app" networks: - weather-forecast-net ports: - "80:80" environment: ASPNETCORE_ENVIRONMENT: Development DOTNET_PRINT_TELEMETRY_MESSAGE: false ConnectionStrings__Postgres: Host=weather-forecast-postgres;User Id=postgres;Password=postgres;Database=postgres ConnectionStrings__Redis: weather-forecast-redis:6379 depends_on: postgres: condition: service_started redis: condition: service_started
Теперь сервис app использует образ из Container Registry вместо сборки из docker-файл. Ещё мы используем порт хота 80.
docker compose up -d
Без удобного клиента Docker Desktop проверить какие контейнеры запущены можно командой:
docker ps
Фаервол на виртуальной машине мы ещё не настраивали, поэтому мы должны увидеть наш сайт снаружи:
И убедившись в том, что всё работает, останавливаем и удаляем контейнеры:
docker compose down
Теперь попробуем запустить наше приложение с базами данных от Selectel. Как создать базы данных в Selectel, вы уже знаете. Я прошлые базы данных удалил, поэтому создаю новые пользуясь своей же инструкцией, удобно =)
cd ~ mkdir dev-db cd dev-db nano ./docker-compose.yml
Содержимое файла docker-compose.yml:
name: "weather-forecast" networks: weather-forecast-net: services: app: image: "cr.selcloud.ru/deploy2production/weather-forecast-app-img:v2.0" container_name: "weather-forecast-app" networks: - weather-forecast-net ports: - "80:80" environment: ASPNETCORE_ENVIRONMENT: Development DOTNET_PRINT_TELEMETRY_MESSAGE: false ConnectionStrings__Postgres: Host=192.168.0.107;User Id=delilah;Password=*******;Database=weatherforecast ConnectionStrings__Redis: 192.168.0.222:6379,password==*********
В этот раз запустим приложение в интерактивном режиме, чтобы увидеть лог:
docker compose up
И мы видим, что приложение успешно запускается и работает, но происходит ошибка при выполнении второго sql-скрипта, который настраивает схему базы данных, создает пользователя для приложения. Вот такой вот сюрприз, пользователь, которого мы создали через интерфейс личного кабинет (а это единственный доступный вариант), просто не имеет необходимых прав. Такое вот ограничение облачной базы данных Postgres в Selectel, связано это с реализацией на стороне Selectel. Но не унываем, значит нам нужно будет учесть этот момент и внести изменения в свой код ;)
Останавливаем приложение, Ctrl+C. Удаляем:
docker compose down
Давайте, для полноты картины создадим compose файлы для приложения и утилиты настройки базы данных так, как бы мы делали в "бою".
cd ~ mkdir prod cd prod mkdir setup cd setup nano ./docker-compose.yml
services: setup: image: "cr.selcloud.ru/deploy2production/weather-forecast-setup-img:v2.0" container_name: "weather-forecast-setup" environment: ConnectionStrings__Postgres: Host=192.168.0.107;User Id=delilah;Password=pwd;Database=weatherforecast
docker compose up
cd ~/prod mkdir app cd app nano ./docker-compose.yml
name: "weather-forecast" networks: weather-forecast-net: services: app: image: "cr.selcloud.ru/deploy2production/weather-forecast-app-img:v2.0" container_name: "weather-forecast-app" networks: - weather-forecast-net ports: - "80:80" environment: ASPNETCORE_ENVIRONMENT: Production DOTNET_PRINT_TELEMETRY_MESSAGE: false ConnectionStrings__Postgres: Host=192.168.0.107;User Id=delilah;Password=pwd;Database=weatherforecast ConnectionStrings__Redis: 192.168.0.222:6379,password==pwd
docker compose up -d
docker compose ps
Подведем итоги. Мы разобрались на базовом уровне как разрабатывать, упаковывать и распространять приложение с помощью docker-а, и запускать его потом на виртуальной машине. Теперь дальше мы будем двигаться глубже =)