В этой статье мы разберём варианты деплоя приложения на ASP.NET Core — от простого к сложному.
Возьмём шаблонное приложение — ToDo List. Оно использует фреймворк ASP.NET Core MVC и базу данных PostgreSQL. При этом у Postgres также есть несколько вариантов развёртывания, от Docker до Managed PostgreSQL.
Приложение на Гитхабе: DmitryBahtenkov/BaseTodoList
Важный нюанс: для корректной работы приложения может потребоваться настроить две переменные окружения:
DATABASE_CONNECTION
— строка подключения к БД.
ASPNETCORE_URLS
— значения адресов, по которым будет доступно приложение.
Самый простой способ развернуть приложение на ASP.NET Core — использовать готовые решения Platform as a Service. Это модель услуг, в которой пользователь получает платформу, где может поднимать различные приложения и управлять ими, абстрагируясь от инфрастуктуры — сетей, серверов и т.д. Это очень удобный подход, поскольку он позволяет сосредоточиться на написании кода и логике приложения, не тратя время на настройку и поддержку серверного оборудования. Также подход позволяет быстро разворачивать приложение, например, для тестирования, в качестве MVP (minimal viable product) или проверки различных гипотез.
Одним из таких решений является Timeweb Cloud Apps. В нём мы просто можем указать ссылку на репозиторий, настроить команды запуска приложения и платформа всё сделает за нас.
Процесс настройки следующий:
Выбираем тип приложения
Выбираем репозиторий с приложением (через интеграцию с GitHub или просто по адресу репозитория)
Указываем команды сборки и запуска
Добавляем переменные окружения
Выбираем мощность сервера
Запускаемся!
Для запуска приложения нужен тип Backend -> ASP.NET Core. Наше тестовое приложение написано на .NET 7, поэтому необходимо явно указать эту версию:
Далее нужно указать репозиторий.
Если ваше приложение есть на вашем аккаунте GitHub, GitLab или Bitbucket, можно войти в систему контроля версий через Timeweb Cloud и выбрать приложение из списка репозиториев.
При входе через GitHub можно указать только конкретные репозитории:
Если у вас нет аккаунта или вы не хотите связывать его со сторонним приложением, можно воспользоваться ссылкой на репозиторий:
После выбора приложения, если вы использовали одну из облачных систем управления репозиториями, можно включить параметр «Сборка по последнему выполненному коммиту». Он позволяет выполнять автоматический редеплой более свежей версии приложения на основе последнего коммита в указанную ветку.
Далее выбираем регион и конфигурацию сервера. Для тестов подойдёт минимальная, но в целом необходимо ориентироваться на потребление ресурсов вашего приложения и планируемую нагрузку на него.
После выбора конфигурации необходимо установить команды сборки и запуска, а также переменные окружения. Обычно команда сборки не требует изменений, но можно явно указать конфигурацию Release для приложения.
В нашем приложении в команде dotnet run
необходимо явно указать запускаемый проект. Это делается с помощью флага --project
.
Также необходимо указать переменные окружения. В данном случае нам нужны:
Переменная со строкой подключения к БД DATABASE_CONNECTION
. Укажите её в формате
Server=<адрес_сервера>;Port=5432;Database=<название_бд>;User Id=<имя_пользователя>;Password=<пароль_пользователя>;
Переменная APP_URL
, которая укажет адрес сервера как 0.0.0.0:5000
. Это необходимо для корректной работы Apps.
После этого нажимаем «Запустить деплой» и смотрим на логи:
После запуска приложения его логи также можно будет посмотреть в отдельной вкладке «Логи приложения».
При необходимости можно изменить настройки вашего приложения: от конфигурации сервера до параметров запуска:
А по адресу сервера или домена будет доступно само приложение:
В этом разделе мы разберём другие способы развёртывания приложения на ASP.NET Core. Они могут быть полезны, если необходима более тонкая настройка инфраструктуры, где будет развёрнуто приложение.
Разберём следующие варианты:
Nginx и Reverse Proxy
Dockerfile
Docker Compose
vds
Что нам потребуется?
VPS c ОС Ubuntu LTS
Nginx
.NET SDK
Характеристики VPS можно рассчитать на основе планируемой нагрузки. Минимальная конфигурация может быть следующая:
1 CPU
1GB RAM
15 - 20 GB Disk
Для более комфортной работы можно взять что-то помощнее, например 2 GB RAM.
После создания сервера необходимо подключиться к нему по SSH и выполнить следующие команды:
sudo apt update && sudo apt install nginx
Проверить корректность установки можно с помощью команды
nginx -v
Когда мы устанавливаем Nginx впервые, то для того, чтобы Nginx запустился, нужно выполнить команду:
sudo service nginx start
По адресу сервера можем увидеть стартовую страницу:
Тестовое приложение использует .net7
. Чтобы установить его, можно воспользоваться инструкцией Установка .NET в Ubuntu в справочном центре Microsoft.
На Ubuntu установка сводится к выполнению команды:
sudo apt-get install -y dotnet-sdk-7.0
Проверить установку можно с помощью команды:
dotnet --version
Сначала клонируем репозиторий себе на сервер:
git clone https://github.com/DmitryBahtenkov/BaseTodoList
И перейдём в папку с проектом:
cd BaseTodoList/
Далее выполняем сборку, чтобы убедиться что всё хорошо:
dotnet build
Собранное приложение необходимо опубликовать с помощью команды dotnet publish
. В параметре -o
необходимо указать директорию, в которой будет лежать исполняемый файл приложения. Обычно это папка по пути /var/www/<приложение>
:
dotnet publish -o /var/www/BaseToDoList
Проверим, что в папке появились файлы приложения:
ls /var/www/BaseToDoList/
Приложение необходимо запустить, указать к нему переменные окружения и реализовать его перезапуск при рестарте сервера. Это можно сделать с помощью 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. Сначала откроем файл по пути /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
И перезапустить Nginx:
sudo service nginx restart
По адресу нашего сервера теперь доступно приложение:
Более подробная инструкция есть в другой статье, где разбирается деплой приложения на ASP.NET Core как раз с помощью Dockerfile. Ниже рассмотрим основные моменты.
Рекомендуемая конфигурация:
1 CPU
2GB RAM
15 - 20 GB Disk
Для этого варианта развёртывания нам потребуется сервер с установленным Docker. Можно установить его вручную, а можно выбрать сервер с уже установленным ПО.
В самом приложении уже предоставлен 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 доступно наше приложение:
Если необходимо развернуть приложение вместе с базой данных на одном сервере — например, в качестве тестового стенда — можно использовать Docker Compose.
Docker Compose — это утилита, которая позволяет управлять приложениями, использующими множество контейнеров. В нашем случае контейнеров будет два:
PostgreSQL
Приложение на ASP.NET
Минимальная конфигурация:
1 CPU
2GB RAM
15 - 20 GB Disk
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
Дождёмся запуска сервиса и перейдём по адресу сервера. Готово!
Разверните свое приложение на VDS/VPS от Timeweb Cloud
В этой статье мы разобрали основные способы развёртывания приложения на ASP.NET Core, от простого, например, решения PaaS, к более сложному — вариантам с ручной настройкой сервера.
Здравствуйте! Подскажите, что делать, если делал все по инструкции первого способа, за исключением подключения базы данных, т.к. ее нет, но постоянно выдает ошибку 502 bad gateway?