Размещение .NET 6 WebAPI на Heroku с PostgreSQL, без контейнера

от автора

Вступление

В интернете не так много информации о том, как можно разместить приложение .NET на облачном сервисе Heroku, в том числе немного сказано о приложениях с БД. Как без мороки и элегантно разместить ваш .NET — проект? Узнаете в этой статье.

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

Технологии

  • .NET 6 WebAPI

  • Heroku

  • Entity Framework Core 6

  • PostgreSQL

Heroku

Регистрируемся на сервисе Heroku. Трудностей быть не должно.

Регистрация в Heroku
Регистрация в Heroku
Создаём новое приложение и указываем его название.
Создаём новое приложение и указываем его название.
Выбираем метод расположения через Github
Выбираем метод расположения через Github

После подключения к GitHub выбираем наш репозиторий с WebAPI, преждевременно выгруженным туда. Также окном ниже выбираем ветвь с приложением, которое загрузится на сервис.

Устанавливаем соединение с github
Устанавливаем соединение с github
Выбираем ветвь репозитория
Выбираем ветвь репозитория

А теперь важный аспект. Перед тем, как деплоить проект, его необходимо собрать.

Переходим во вкладку Settings и в пункте Buildpacks добавляем ссылку на «сборочный пакет» .NET 6.

Buildpacks
Buildpacks

https://github.com/jincod/dotnetcore-buildpack

Осталось следующее: установить аддон Heroku Postgres с помощью Configure Add-ons во вкладке Overview:

Postgres add-on
Postgres add-on

Кликаем по аддону и переходим во вкладку Settings >> View Credentials, где находятся данные о нашей БД. Они нам понадобятся.

Database Credentials
Database Credentials

Конфигурационные файлы

Переходим во вкладку Settings >> Config Vars и добавим конфигурационный файл под именем "ASPNETCORE_ENVIRONMENT". Это файл ключ-значение в котором будет удобно конфигурировать нашу рабочую среду между Development / Production значениями.

Config Vars
Config Vars

Также здесь можно заметить такой файл как "DATABASE_URL". Это строка подключения к БД, предоставленная аддоном Heroku. Мы её будем использовать

Наш проект практически готов к публикации. Осталось его настроить.

Настройка проекта

Сразу скажу, что структура проекта, безусловно, может у каждого отличаться, но алгоритм действий будет одинаков при любом раскладе. Я продемонстрирую CRUD-проект. Условимся на том, что у вас объявлены соответствующие классы и сущности и осталось только настроить слой базы данных. Кратко ознакомимся.

Тема проекта: книжный магазин.

Приложение разделено на слои:

  • Domain (сущности)

  • Application (бизнес-логика)

  • Persistence (слой доступа к данным)

  • Presentation (web api)

Структура проекта
Структура проекта

 Убедимся, что в сборке со слоем БД установлены все необходимые NuGet пакеты:

Пакеты NuGet
Пакеты NuGet

Если вы все делаете в одной сборке WebApi, этих пакетов будет достаточно.

Настройка контекста базы данных

Создадим интерфейс, который будет реализован контекстом BookStoreDbContext:

public interface IBookStoreDbContext     {         DbSet<Book> Books { get; set; }         Task<int> SaveChangesAsync(CancellationToken cancellationToken);     }

Объявим необходимые таблицы и вызываем базовый конструктор. В этом же классе можно переопределить protected метод OnModelCreating(), чтобы добавить начальные данные в таблицу, но это уже за рамками статьи.

    public class BookStoreDbContext : DbContext, IBookStoreDbContext     {         public DbSet<Book> Books { get; set; }         public BookStoreDbContext(DbContextOptions<BookStoreDbContext> options)             : base(options) { }     }

Создадим класс DbInitializer, который будет использоваться при старте приложения и будет проверять, создана ли наша БД, и если нет, то создаст на основе нашего контекста. Также важно вызвать метод Migrate() нашей БД, чтобы миграция накатывалась програмным способом и сервер Heroku смог её вызвать:

    public class DbInitializer     {         public static void Initialize(BookStoreDbContext context)         {             context.Database.EnsureCreated();             context.Database.Migrate();         }     }

Переходим в файл конфигурации приложения appsettings.json, где укажем строку подключения DbConnectionнашей локальной БД.

Вместо # — укажите ваши данные:

{   "Logging": {     "LogLevel": {       "Default": "Information",       "Microsoft.AspNetCore": "Warning"     }   },   "ConnectionStrings": {     "DbConnection": "Host=localhost;Database=#;Username=#;"   },   "AllowedHosts": "*" } 

Внедрение зависимостей

Добавим класс DependencyInjection для нашего контекста. В нем мы внедрим наш контекст базы данных.

Создадим метод GetConnectionString(), который получит данные о строке подключения из конфигурационного файла Heroku "DATABASE_URL".

Если в конфигурационном файле указана среда "Development" (разработка), то мы используем нашу локальную строку подключения к БД в файле asppsettings.json с её строкой подключения.

Подключим PostgreSql.

    public static class DependencyInjection     {         public static IServiceCollection AddPersistence(             this IServiceCollection services,             IConfiguration configuration)         {             var connectionString = string.Empty;           /* Проверим, в какой мы среде*/             if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development")             {                 connectionString = configuration["DbConnection"];             }             else             {                 connectionString = GetConnectionString();             }              services.AddDbContext<BookStoreDbContext>(options =>             {               /* Подключаем PostgreSQL */                 options.UseNpgsql(connectionString);             });             services.AddScoped<IBookStoreDbContext>(provider =>                 provider.GetService<BookStoreDbContext>());              return services;         }          public static string GetConnectionString()         {              /* Используем строку подключения из конфигурацинного файла, обеспеченного Heroku*/             var connectionUrl = Environment.GetEnvironmentVariable("DATABASE_URL");              connectionUrl = connectionUrl.Replace("postgres://", string.Empty);             var userPassSide = connectionUrl.Split("@")[0];             var hostSide = connectionUrl.Split("@")[1];              var user = userPassSide.Split(":")[0];             var password = userPassSide.Split(":")[1];             var host = hostSide.Split("/")[0];             var database = hostSide.Split("/")[1].Split("?")[0];              return $"Host={host};Database={database};Username={user};Password={password};SSL Mode=Require;Trust Server Certificate=true";         }

В файле Program.cs нашего WebAPI внедрим контекст БД и вызовем необходимый метод Initialize():

using (var scope = app.Services.CreateScope()) {     try     {         var context = scope.ServiceProvider.GetRequiredService<BookStoreDbContext>();         DbInitializer.Initialize(context);     }     catch (Exception)     {     } }

Добавим миграцию в проект с помощью команды add-migration Init:

Package Manager Console
Package Manager Console

Деплоим проект!

Вернёмся в Heroku и нажмём заветную кнопку Deploy Branch:

Manual Deploy
Manual Deploy

Заключение

Поздравляю! Можно переходить на сайт. Вы можете наблюдать за состоянием сборки вашего приложения во вкладке Activity.

В моём случае это получение информации о книгах.

API response
API response

Я надеюсь, что изложил максимально просто и понятно. Если исключить БД, то всего лишь необходимо подключить .NET buildpack и деплоить проект. Проблем быть не должно.

Всех благ!

Дополнительная информация

Heroku:

https://dashboard.heroku.com/

Ролик, который вдохновил меня на написание статьи:

https://www.youtube.com/watch?v=BqI1hu0gIb0&ab_channel=CoderFoundry

Аналогичная статья с размещением API вместе с Docker:

https://www.c-sharpcorner.com/article/deploy-a-net-api-to-heroku-through-github-actions/

Создание контекста БД и подключение PostgreSQL с помощью Entity Framework Core:

https://www.npgsql.org/efcore/

На всякий случай добавлю .NET Buildpack для размещения вашего приложения:

https://github.com/jincod/dotnetcore-buildpack

Более подробное описание добавления Entity Framework Core в проект:

https://www.youtube.com/watch?v=wkF3csnu2hE&list=PLEtg-LdqEKXbpq4RtUp1hxZ6ByGjnvQs4&index=3&ab_channel=PlatinumDEV


ссылка на оригинал статьи https://habr.com/ru/post/695234/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *