Больше не нужно искать работу мечты — присоединяйтесь к команде Клауда

Как развернуть приложение ASP.NET Core в Timeweb Cloud Apps и не только

Дмитрий Бахтенков
Дмитрий Бахтенков
Технический писатель
05 июня 2024 г.
297
11 минут чтения
Средний рейтинг статьи: 5

В этой статье мы разберём варианты деплоя приложения на ASP.NET Core — от простого к сложному.

Что будем разворачивать?

Возьмём шаблонное приложение — ToDo List. Оно использует фреймворк ASP.NET Core MVC и базу данных PostgreSQL. При этом у Postgres также есть несколько вариантов развёртывания, от Docker до Managed PostgreSQL.

Приложение на Гитхабе: DmitryBahtenkov/BaseTodoList

Важный нюанс: для корректной работы приложения может потребоваться настроить две переменные окружения:

  • DATABASE_CONNECTION — строка подключения к БД.

  • ASPNETCORE_URLS — значения адресов, по которым будет доступно приложение.

PaaS (Timeweb Cloud Apps)

Самый простой способ развернуть приложение на ASP.NET Core — использовать готовые решения Platform as a Service. Это модель услуг, в которой пользователь получает платформу, где может поднимать различные приложения и управлять ими, абстрагируясь от инфрастуктуры — сетей, серверов и т.д. Это очень удобный подход, поскольку он позволяет сосредоточиться на написании кода и логике приложения, не тратя время на настройку и поддержку серверного оборудования. Также подход позволяет быстро разворачивать приложение, например, для тестирования, в качестве MVP (minimal viable product) или проверки различных гипотез.

Одним из таких решений является Timeweb Cloud Apps. В нём мы просто можем указать ссылку на репозиторий, настроить команды запуска приложения и платформа всё сделает за нас.

Процесс настройки следующий:

  • Выбираем тип приложения

  • Выбираем репозиторий с приложением (через интеграцию с GitHub или просто по адресу репозитория)

  • Указываем команды сборки и запуска

  • Добавляем переменные окружения

  • Выбираем мощность сервера

  • Запускаемся!

Image8

Для запуска приложения нужен тип Backend -> ASP.NET Core. Наше тестовое приложение написано на .NET 7, поэтому необходимо явно указать эту версию:

Image19

Далее нужно указать репозиторий. 

Image5

Если ваше приложение есть на вашем аккаунте GitHub, GitLab или Bitbucket, можно войти в систему контроля версий через Timeweb Cloud и выбрать приложение из списка репозиториев.

При входе через GitHub можно указать только конкретные репозитории:

Image3

Если у вас нет аккаунта или вы не хотите связывать его со сторонним приложением, можно воспользоваться ссылкой на репозиторий:

Image10

После выбора приложения, если вы использовали одну из облачных систем управления репозиториями, можно включить параметр «Сборка по последнему выполненному коммиту». Он позволяет выполнять автоматический редеплой более свежей версии приложения на основе последнего коммита в указанную ветку. 

66d3fc60 D830 4834 B62c 4783e5f260b3

Далее выбираем регион и конфигурацию сервера. Для тестов подойдёт минимальная, но в целом необходимо ориентироваться на потребление ресурсов вашего приложения и планируемую нагрузку на него.

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

2ddfbaa7 B041 44d7 Af16 78ab39b9eaf4

В нашем приложении в команде dotnet run необходимо явно указать запускаемый проект. Это делается с помощью флага --project.

Также необходимо указать переменные окружения. В данном случае нам нужны:

  • Переменная со строкой подключения к БД DATABASE_CONNECTION. Укажите её в формате 

Server=<адрес_сервера>;Port=5432;Database=<название_бд>;User Id=<имя_пользователя>;Password=<пароль_пользователя>;
  • Переменная APP_URL, которая укажет адрес сервера как 0.0.0.0:5000. Это необходимо для корректной работы Apps.

После этого нажимаем «Запустить деплой» и смотрим на логи:

Image13

После запуска приложения его логи также можно будет посмотреть в отдельной вкладке «Логи приложения».

При необходимости можно изменить настройки вашего приложения: от конфигурации сервера до параметров запуска:

Image17

А по адресу сервера или домена будет доступно само приложение:

Image9

Другие способы деплоя приложения

В этом разделе мы разберём другие способы развёртывания приложения на ASP.NET Core. Они могут быть полезны, если необходима более тонкая настройка инфраструктуры, где будет развёрнуто приложение.

Разберём следующие варианты:

  • Nginx и Reverse Proxy

  • Dockerfile

  • Docker Compose

vds

Reverse-Proxy на VPS (NGINX)

Подготовка

Что нам потребуется?

  • VPS c ОС Ubuntu LTS

  • Nginx

  • .NET SDK

Характеристики VPS можно рассчитать на основе планируемой нагрузки. Минимальная конфигурация может быть следующая:

  • 1 CPU

  • 1GB RAM

  • 15 - 20 GB Disk

Для более комфортной работы можно взять что-то помощнее, например 2 GB RAM. 

Устанавливаем Nginx

После создания сервера необходимо подключиться к нему по SSH и выполнить следующие команды:

sudo apt update && sudo apt install nginx

Проверить корректность установки можно с помощью команды 

nginx -v

Когда мы устанавливаем Nginx впервые, то для того, чтобы Nginx запустился, нужно выполнить команду:

sudo service nginx start

По адресу сервера можем увидеть стартовую страницу:

Image21

Устанавливаем dotnet

Тестовое приложение использует .net7. Чтобы установить его, можно воспользоваться инструкцией Установка .NET в Ubuntu в справочном центре Microsoft.

На Ubuntu установка сводится к выполнению команды:

sudo apt-get install -y dotnet-sdk-7.0

Проверить установку можно с помощью команды:

dotnet --version

Image12

Запускаем приложение на ASP.NET

Сначала клонируем репозиторий себе на сервер:

git clone https://github.com/DmitryBahtenkov/BaseTodoList

И перейдём в папку с проектом:

cd BaseTodoList/

Далее выполняем сборку, чтобы убедиться что всё хорошо:

dotnet build

De0d4b87 227f 4b2a 8815 C2e1b02c814c

Собранное приложение необходимо опубликовать с помощью команды dotnet publish. В параметре -o необходимо указать директорию, в которой будет лежать исполняемый файл приложения. Обычно это папка по пути /var/www/<приложение>:

dotnet publish -o /var/www/BaseToDoList

Image2

Проверим, что в папке появились файлы приложения:

ls /var/www/BaseToDoList/

Image16

Приложение необходимо запустить, указать к нему переменные окружения и реализовать его перезапуск при рестарте сервера. Это можно сделать с помощью systemctl.

Добавим файл сервиса:

[Unit]
Description=Base ToDo List for TimeWeb Article

[Service]
WorkingDirectory=/var/www/BaseToDoList
ExecStart=/usr/bin/dotnet /var/www/BaseToDoList/BaseToDoList.dll
Restart=always
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=base-todo-list
User=root
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DATABASE_CONNECTION='Server=<адрес_сервера>;Port=5432;Database=<название_бд>;User Id=<имя_пользователя>;Password=<пароль_пользователя>;'
Environment=ASPNETCORE_URLS='http://localhost:5000'

[Install]
WantedBy=multi-user.target

Настраиваем Nginx

Теперь настроим Nginx. Сначала откроем файл по пути /etc/nginx/sites-available/default в текстовом редакторе (например, nano) и поместим туда следующий код конфигурации:

  # Создание переменной $connection_upgrade, зависящей от значения заголовка $http_connection
  map $http_connection $connection_upgrade {
    "~*Upgrade" $http_connection;
    default keep-alive;
  }

  server {
    listen        80; # Настройка сервера на прослушивание порта 80
    server_name   example.com *.example.com; # Обработка запросов для домена example.com и всех его поддоменов
    location / {
        proxy_pass         http://127.0.0.1:5000/; # Перенаправление запросов на локальный сервер на порт 5000
        proxy_http_version 1.1; # Использование HTTP версии 1.1 при проксировании запросов
        proxy_set_header   Upgrade $http_upgrade; # Передача заголовка Upgrade из оригинального запроса в проксированный запрос
        proxy_set_header   Connection $connection_upgrade; # Передача заголовка Connection из оригинального запроса в проксированный запрос
        proxy_set_header   Host $host; # Передача заголовка Host из оригинального запроса в проксированный запрос
        proxy_cache_bypass $http_upgrade; # Обход кэширования для запросов, содержащих заголовок Upgrade
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for; # Добавление заголовка X-Forwarded-For для передачи информации об IP-адресе клиента через прокси
        proxy_set_header   X-Forwarded-Proto $scheme; # Передача информации о протоколе (HTTP или HTTPS) клиента через прокси
    }
  }

После заполнения файла выполним команду для включения нашей конфигурации: 

sudo ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default

Далее можем проверить конфигурацию с помощью:

sudo nginx -t

Image14

И перезапустить Nginx:

sudo service nginx restart

По адресу нашего сервера теперь доступно приложение:

Image9

Docker

Более подробная инструкция есть в другой статье, где разбирается деплой приложения на ASP.NET Core как раз с помощью Dockerfile. Ниже рассмотрим основные моменты.

Рекомендуемая конфигурация:

  • 1 CPU

  • 2GB RAM

  • 15 - 20 GB Disk

Для этого варианта развёртывания нам потребуется сервер с установленным Docker. Можно установить его вручную, а можно выбрать сервер с уже установленным ПО.

Dockerfile 

В самом приложении уже предоставлен Dockerfile. Разберём его:

# Используем официальный образ ASP.NET Core 7.0 в качестве базового для нашего приложения
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base

# Устанавливаем рабочую директорию внутри контейнера для приложения
WORKDIR /app

# Открываем порт 80 для HTTP-трафика
EXPOSE 80

# Используем официальный образ .NET SDK 7.0 для сборки приложения
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build

# Задаем аргумент для конфигурации сборки, по умолчанию это Release
ARG BUILD_CONFIGURATION=Release

# Устанавливаем рабочую директорию для исходного кода приложения
WORKDIR /src

# Копируем файл проекта в контейнер для восстановления зависимостей
COPY ["BaseToDoList/BaseToDoList.csproj", "BaseToDoList/"]

# Восстанавливаем зависимости, указанные в файле проекта
RUN dotnet restore "BaseToDoList/BaseToDoList.csproj"

# Копируем все оставшиеся файлы исходного кода в контейнер
COPY . .

# Устанавливаем рабочую директорию внутри контейнера для проекта
WORKDIR "/src/BaseToDoList"

# Собираем проект в конфигурации Release и выводим результат в указанную директорию
RUN dotnet build "BaseToDoList.csproj" -c $BUILD_CONFIGURATION -o /app/build

# Создаем новый этап публикации, который наследует предыдущий этап сборки
FROM build AS publish
ARG BUILD_CONFIGURATION=Release

# Публикуем приложение в конфигурации Release, указывая выходную директорию и отключая использование AppHost
RUN dotnet publish "BaseToDoList.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false

# Создаем финальный этап на основе базового образа ASP.NET Core
FROM base AS final

# Устанавливаем рабочую директорию внутри контейнера для опубликованного приложения
WORKDIR /app

# Копируем опубликованные файлы из предыдущего этапа в рабочую директорию
COPY --from=publish /app/publish .

# Устанавливаем точку входа для запуска приложения в контейнере
ENTRYPOINT ["dotnet", "BaseToDoList.dll"]

Развернуть приложение можно двумя способами: просто собрав docker-контейнер на сервере или с помощью Docker Registry.

Сборка контейнера

Подключимся на сервер с помощью SSH, склонируем проект и перейдём в папку с проектом.

git clone https://github.com/DmitryBahtenkov/BaseTodoList
cd BaseTodoList
docker build . -t todolist:lts

После сборки контейнера запустим его, указав в переменной окружения строку подключения к БД:

docker run -p 5000:5000 -d -e DATABASE_CONNECTION='Server=<адрес_сервера>;Port=5432;Database=<название_бд>;User Id=<имя_пользователя>;Password=<пароль_пользователя>;' -e APP_URL='http://0.0.0.0:5000' todolist:lts

По адресу сервера и порту 5000 доступно наше приложение:

Image9

Docker Compose на VPS

Если необходимо развернуть приложение вместе с базой данных на одном сервере — например, в качестве тестового стенда — можно использовать Docker Compose.

Docker Compose — это утилита, которая позволяет управлять приложениями, использующими множество контейнеров. В нашем случае контейнеров будет два:

  • PostgreSQL

  • Приложение на ASP.NET

Минимальная конфигурация:

  • 1 CPU

  • 2GB RAM

  • 15 - 20 GB Disk

Файл docker-compose

services:
  # Определяем сервис "todolist.app"
  todolist.app:
    # Собираем образ из указанного Dockerfile в текущем контексте
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "5000:5000"
    # Устанавливаем переменные окружения для контейнера
    environment:
      # Устанавливаем строку подключения к базе данных
      DATABASE_CONNECTION: "Server=postgresql.docker;Port=5432;Database=todo;User Id=todo_owner;Password=password;"
      APP_URL: "http://0.0.0.0:5000"
  
  # Определяем сервис "postgresql"
  postgresql:
    # Используем образ PostgreSQL версии 15
    image: postgres:15
    # Устанавливаем переменные окружения для PostgreSQL
    environment:
      # Устанавливаем имя базы данных
      POSTGRES_DB: "todo"
      # Устанавливаем имя пользователя базы данных
      POSTGRES_USER: "todo_owner"
      # Устанавливаем пароль пользователя базы данных
      POSTGRES_PASSWORD: "password"
      # Указываем путь к данным PostgreSQL внутри контейнера
      PGDATA: "/var/lib/postgresql/data/pgdata"
    # Монтируем текущий каталог внутрь контейнера PostgreSQL для сохранения данных
    volumes:
      - .:/var/lib/postgresql/data
    # Открываем порт хоста для доступа к PostgreSQL извне
    ports:
      - "5432:5432"
    # Перезапускаем контейнер, если он остановлен, кроме случаев, когда его явно остановили
    restart: unless-stopped
    # Устанавливаем имя хоста контейнера
    hostname: "postgresql.docker"

Запуск на сервере

Снова склонируем репозиторий с помощью команды git clone и перейдём в папку с проектом:

git clone https://github.com/DmitryBahtenkov/BaseTodoList
cd BaseTodoList

Далее выполним команду:

docker compose up -d

Дождёмся запуска сервиса и перейдём по адресу сервера. Готово!

Image9

Разверните свое приложение на VDS/VPS от Timeweb Cloud

Заключение

В этой статье мы разобрали основные способы развёртывания приложения на ASP.NET Core, от простого, например, решения PaaS, к более сложному — вариантам с ручной настройкой сервера.

Хотите внести свой вклад?
Участвуйте в нашей контент-программе за
вознаграждение или запросите нужную вам инструкцию
img-server
05 июня 2024 г.
297
11 минут чтения
Средний рейтинг статьи: 5
Комментарии 1
Андрей
27.08.2024, 18:44

Здравствуйте! Подскажите, что делать, если делал все по инструкции первого способа, за исключением подключения базы данных, т.к. ее нет, но постоянно выдает ошибку 502 bad gateway?