В предыдущей статье я показывал вам, как создать веб-приложение .net5 с конечной целью - контейнеризовать его с помощью докера.

В этой второй части путешествия я покажу вам, как заставить ваше веб-приложение потреблять данные из вашей собственной базы данных и как превратить это в сценарий докера, в котором веб-приложение .net5 контейнер безопасно взаимодействует с контейнером базы данных.

Предварительные требования:

Если вам нужна помощь или вы столкнулись с неожиданными ошибками, ознакомьтесь с кратким разделом об устранении неполадок в конце этой статьи или оставьте ответ. Я буду следить за этим и буду рад помочь.

Прежде всего, позвольте мне поставить цель, чтобы в этом упражнении / руководстве было немного смысла. Одна вещь, которую я люблю отслеживать, - это то, как я использую свое время. Мы импортируем аэропорты в США, после чего веб-приложение .net визуализирует их для нас. Эти данные становятся общедоступными в рамках задачи Kaggle (https://www.kaggle.com/usdot/ задержки рейсов )

PostgreSQL, моя любимая база данных

Это не место, чтобы начинать дискуссию о лучшей базе данных sql или о том, лучше ли выбрать nosql. Я сертифицированный эксперт Oracle, а также работал с MS SQL Server, MySQL, SAP HANA и PostgreSQL в продуктивных средах. Поскольку у всех есть свои плюсы и минусы, я выберу для вас PostgreSQL. Почему? Мне нравятся расширенные типы данных, пространственные возможности, и это отличный выбор, если вы «не совсем уверены, чем закончится этот проект».

Чтобы избежать путаницы и действий при установке, зависящей от платформы, мы сначала создадим этот контейнер db, а затем настроим веб-приложение. Используйте docker pull, чтобы загрузить образ базы данных postgres из концентратора докеров. Откройте оболочку терминала (или командную строку Windows) и выполните следующую команду:

docker pull postgres

Вы увидите несколько загрузок консоли и окончательное сообщение о статусе. Это означает, что образ доступен локально и что контейнер можно запустить, как я показал вам в части первой этой серии статей. Конечный postgres - это имя изображения, которое будет использоваться. Убедитесь, что это введено в терминал как одна строка.

docker run --name webappdb -p 5432:5432 -e POSTGRES_PASSWORD=newton243 -d postgres

Убедитесь, что контейнер был запущен:

docker ps -a

Как видно на скриншоте выше, порт 5432 (стандартный порт postgres) на локальном хосте сопоставлен с портом 5432 внутри контейнера.

Самый удобный способ работы с базами данных - это использовать инструмент администрирования баз данных, и я бы рекомендовал это, даже если вы опытный пользователь оболочки. Мой любимый инструмент - DBeaver (доступен здесь и поставляется с установщиком https://dbeaver.io/) , который не зависит от платформы и позволяет мне работать с несколькими различными базы данных параллельно. Но вы также можете использовать pgadmin или что-то еще.

Подключение к PostgresSQL и создание данных

Откройте DBeaver и щелкните символ штекера под «Файл», чтобы открыть мастер подключения (показанный ниже) и выполнить поиск по запросу «postgres», выберите получившийся PostgreSQL и нажмите «Далее»…

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

Выглядит хорошо! Нажмите «Готово» сейчас, а затем разверните соединение с именем «postgres» в навигаторе базы данных.

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

Мы не будем усложнять задачу созданием отдельной схемы базы данных и т. Д., А просто будем использовать доступную базу данных postgres и существующую схему public.

Пришло время загрузить копию flightnet_airports.csv из репозитория github одной из моих других статей (https://github.com/martinhorvath/com.primebird.graphplayground, щелкните файл , затем нажмите raw на верхней панели, а затем щелкните правой кнопкой мыши и нажмите Сохранить как на странице с содержимым csv)

DBeaver имеет удобную функцию импорта csv, которая создает для нас таблицу. Щелкните правой кнопкой мыши «общедоступный» на изображении выше и выберите «Импортировать данные». CSV в качестве источника предварительно выбран, и вы можете нажать «Далее». Выберите только что загруженный файл и перейдите к настройкам импортера по умолчанию.

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

Опытный пользователь SQL заметит, что широту и долготу нельзя рассматривать как varchar и что iata_code когда-либо будет занимать столько места. Пожалуйста, извините за грязь, поскольку SQL действительно просто препятствие в этом пошаговом руководстве.

Вы можете предварительно просмотреть созданный контент, используя вкладку «Данные». Прежде чем мы продолжим работу со стороны .net, давайте подготовим запрос SQL, чтобы получить все аэропорты из этой базы данных, так как это понадобится нам позже. Выберите запись flightnet_airports в навигаторе базы данных, а затем выберите Редактор SQL - ›Новый редактор SQL в строке меню. В открывшемся окне введите следующий SQL-запрос, выполните его, нажав ctrl + return или маленькую кнопку воспроизведения на вертикальной панели значков, и убедитесь, что возвращается список аэропортов, как показано ниже:

Вы получите тот же результат? Здорово! Тогда вы готовы к части .net.

Ле резюмирует, чего мы достигли к настоящему моменту:

  • Вытащил образ PostgreSQL из Docker Hub
  • Создан новый контейнер PostgreSQL и открыт порт 5432
  • Подключено к экземпляру контейнера и импортированы данные CSV.

Подключение веб-приложения .net5 к PostgreSQL

Общая цель - прочитать только что созданные аэропорты из веб-приложения, чтобы их можно было отобразить на веб-странице. Откройте свои источники (загрузите из моего репозитория на github, если вы пропустили первую часть этого путешествия: https://github.com/martinhorvath/com.primebird.net5webapp/releases/tag/v1)

Класс для аэропорта

Прежде всего, нам нужен класс для объекта с именем airport. Я предпочитаю помещать классы для сущностей в выделенную папку / пакет. Щелкните правой кнопкой мыши где-нибудь ниже Startup.cs и создайте папку с именем entity. Затем щелкните правой кнопкой мыши новую папку и выберите Новый файл. Назовите его Airport.cs и откройте файл.

Чтобы проложить путь новым разработчикам, краткое объяснение того, что происходит сейчас: классы можно рассматривать как чертежи реальных объектов, и несколько объектов могут быть созданы из одного и того же класса. Классы имеют свойства с уникальными именами и предопределенным типом данных. Затем эти свойства заполняются реальными значениями для каждого объекта.

Таблица flightnet_airports станет классом в нашем приложении. Каждый столбец станет свойством в классе (Airport.cs). Каждая строка таблицы станет объектом типа Airport в приложении .net.

Добавьте в файл следующие строки, чтобы определить пространство имен (используемое для группировки классов вместе) и создать в нем класс. Public используется, чтобы не ограничивать доступ к этому классу.
Внутри класса создается несколько свойств. Они помечены как общедоступные, чтобы любой другой класс мог их использовать. Второй аргумент - это тип данных, и мы используем строковый (т.е. текст) и двойной (то есть с плавающей запятой) для широты и долготы.

В реальном приложении мы не объявляем все общедоступным, а также используем геттеры и сеттеры. Но послушайте, сначала простота, чтобы облегчить жизнь новичков (пожалуйста, поищите в Интернете геттеры и сеттеры C #).

namespace aspnetcore_webapp.Entities
{
  public class Airport
  {
    public string iata_code;
    public string airport;
    public string city;
    public string state;
    public string country;
    public double latitude;
    public double longitude;
  }
}

Теперь мы немного отклонимся от обычных практических руководств. Мы отложим все вопросы, связанные с подключением к базе данных, и попытаемся достичь чего-то, что уже имеет смысл для менее опытных разработчиков. Эй… все были на этой стадии в прошлом, и я много раз спрашивал себя: «Что, черт возьми, я здесь делаю». Чтобы этого избежать, мы создадим ярлык и будем использовать этот класс на уже существующей странице приветствия нашего веб-приложения. Откройте Index.cshtml.cs:

Метод OnGet вызывается перед загрузкой этой страницы, и мы сами создадим первый аэропорт для целей тестирования. Для этого нам нужно импортировать пространство имен с нашей моделью. Это сделано путем вставки следующего сразу после последнего оператора using…. Значение должно соответствовать пространству имен, объявленному в Airport.cs

using aspnetcore_webapp.Entities;

Затем мы хотим сделать экземпляр Airport доступным в модели страницы. Это делается путем вставки следующего текста прямо над объявлением переменной _logger:

public Airport myAirport;

Последнее, что мы хотим сделать, - это присвоить этой переменной реальный объект аэропорта. Мы делаем это внутри метода OnGet, чтобы он выглядел следующим образом:

public void OnGet() {
  myAirport = new Airport();
  myAirport.airport = "New York JFK";
  myAirport.city = "New York";
  myAirport.country = "USA";
  myAirport.iata_code = "JFK";
  myAirport.latitude = 0;
  myAirport.longitude = 0;
  myAirport.state = "New York";
}

Мы можем напрямую установить значения этих переменных, потому что мы объявили их общедоступными в классе Airport. Если бы мы использовали private, мы бы не увидели или не смогли бы получить доступ к этой переменной. На этом все готово, и ваш файл должен выглядеть следующим образом:

Последним недостающим элементом, прежде чем мы сможем проверить результат, является использование нашей новой переменной модели в представлении / рендеринге. Представление, относящееся к этому Index.cshtml.cs, называется аналогичным, только без расширения .cs. Итак, откройте сейчас Index.cshtml в редакторе и добавьте следующий код в конец файла:

<div class="text-center">
  <h1 class="display-4">@Model.myAirport.airport</h1>
  <p>This airport is in @Model.myAirport.country and identified by iata code @Model.myAirport.iata_code</p>
</div>

Как видите, переменная myAirport, которую мы определили в классе IndexModel в Index.cshtml.cs, доступна как свойство Модель. Доступ к переменным всегда осуществляется с помощью символа @, который знакомит с кодом C #. Переменная Модель создается автоматически. Ваш окончательный файл должен выглядеть следующим образом:

Теперь попробуйте и начните отладку веб-приложения (Выполнить - ›начать отладку), перейдите по адресу https: // localhost: 5001 и цените результат :-)

Подключение к базе данных и чтение аэропортов

Это было легко, правда? Все, что нам нужно сейчас, - это удалить наш жестко заданный аэропорт единственный аэропорт и вместо этого получить список аэропортов, используя таблицу базы данных.
Но шаг за шагом … Подведем итоги того, что мы будем делать в первую очередь:

  • Установите соединение с базой данных, когда страница будет подготовлена
  • Прочитать все аэропорты с помощью sql-запроса
  • Передайте список аэропортов в IndexPageModel
  • Сделайте такой абзац, как указано выше, для каждого возвращенного аэропорта

Первое, что нам нужно добавить, - это соответствующий драйвер для подключения к Postgres. Это называется Npgsql и доступно в виде пакета nuget. Nuget - это инструмент, который позволяет нам загружать и использовать дополнительные пакеты .net в нашем приложении. Есть и другие способы получить дополнительные пакеты, но я бы сказал, что это наиболее удобный способ.

Откройте терминал внутри VisualStudioCode (строка меню Терминал - ›Новый терминал) и убедитесь, что вы находитесь в правильной папке (в корне вашего веб-приложения, где находится Startup.cs. Вы можете выполнить ls в Linux / Mac OS или dir в системах Windows.

Теперь введите следующую команду, чтобы пакет Npgsql был загружен и зарегистрирован в нашем приложении (как описано здесь: https://www.nuget.org/packages/Npgsql/).

dotnet add package Npgsql

Незаметно для себя этот пакет кэшируется в вашей локальной системе, а ссылка на пакет добавляется в файл csproj вашего решения. Никакой черной магии.

Вернитесь к файлу Index.cshtml.cs, чтобы удалить переменную myAirport и создать новую переменную типа IList, куда мы поместим все наши аэропорты в:

public Airport myAirport; // <--- remove this
public IList<Airport> airports; // <-- add this instead

Мы пока не использовали коллекции в этом файле, поэтому будет показано предупреждение. Либо используйте желтую лампочку, чтобы импортировать рекомендованное пространство имен, либо добавьте его под другим с помощью… вверху файла:

using System.Collections.Generic;

Следующее, что мы хотим сделать, - это написать метод, который заключает в себе весь код базы данных для чтения аэропортов. Я не хочу путать здесь разные шаблоны, методологии и т. Д., Такие как синглтоны, DataAccessObjects, ObjectRelationalMappers. То, что мы здесь делаем, идеально подходит для изучения и понимания концепции, без навигации по множеству файлов, отладки различных уровней приложения и отслеживания мелких досадных ошибок.

Прямо под закрывающей фигурной скобкой OnGet мы добавляем новый частный класс, который мы называем GetAirports и который возвращает список аэропортов. . Позвольте мне сначала вставить код (для тревожных), а потом я вам объясню:

private IList<Airport> GetAirports()
{
    IList<Airport> airports = new List<Airport>();
    var connString = "Host=localhost;Username=postgres;Password=newton243;Database=postgres";
using (var conn = new NpgsqlConnection(connString))
    {
        conn.Open();
using (var cmd = new NpgsqlCommand("SELECT * FROM flightnet_airports", conn))
        {
            using (var reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                {
                    Airport myAirport = new Airport();
                    myAirport.airport = (string)reader["airport"];
                    myAirport.city = (string)reader["city"];
                    myAirport.country = (string)reader["country"];
                    myAirport.iata_code = (string)reader["iata_code"];
                    myAirport.latitude = 0;
                    myAirport.longitude = 0;
                    myAirport.state = (string)reader["state"];
                    airports.Add(myAirport);
                }
            }
        }
    }
    return airports;
}

Сверху вниз происходит следующее: в строке 1 объявляется новый метод с возвращаемым типом IList ‹Airport›, который представляет собой список, который может содержать только объекты типа Airport. Он называется GetAirports и вызывается без аргументов. Вот почему круглые скобки пусты. Он также объявлен как private, что делает его доступным только для функций внутри класса IndexModel, объявленного в том же файле.

Затем мы объявляем новую переменную внутри этого метода с именем airport как пустой список аэропортов.

Для подключения к базе данных требуется строка подключения, содержащая такую ​​информацию, как хост базы данных, имя пользователя и т. Д. Она объявляется с помощью var, который сообщает компилятору определить тип самой переменной. Мы также могли бы написать string connString =….

var connString = "Host=localhost;Username=postgres;Password=newton243;Database=postgres";

Затем следует using-block. Это удобно, когда используются экземпляры объектов, которые мы должны переработать после использования. Т.е. мы не хотим закрывать соединение с базой данных после завершения работы. Это можно использовать только в том случае, если объект, указанный в скобках, поддерживает это.

using (var conn = new NpgsqlConnection(connString))

Здесь мы также используем недавно добавленный пакет nuget Npgsql, который делает доступным NpgsqlConnection и обрабатывает технические вопросы подключения к базе данных. Ему просто нужна строка подключения с правильной информацией. Для использования этого соединения нам также необходимо явно открыть соединение, что и будет сделано сразу после этого. Это можно сравнить с тем, что мы делали ранее с DBeaver при подключении к нашей базе данных внутри докера.

Открыв соединение, мы можем создавать команды с SQL-запросами, как мы это делали в DBeaver:

using (var cmd = new NpgsqlCommand("SELECT * FROM flightnet_airports", conn))

Он снова заключен в оператор using для повторного использования того, что было сделано. NpgsqlCommand требует выполнения SQL-запроса и выполнения NpgsqlConnection. Мы используем созданный ранее conn.

Мы почти закончили ... при выполнении этой команды мы можем использовать класс NpgsqlDataReader, который позволяет нам обрабатывать результаты строка за строкой. Поэтому мы создаем его (снова используя оператор using) следующим образом:

using (var reader = cmd.ExecuteReader())

Этот читатель теперь открыт, и мы можем получать построчно, пока в наборе результатов остаются строки. При запуске в этой итерации указатель перемещается вперед, пока не будет достигнута самая последняя строка. В последнем случае он вернет false и вызовет выход из цикла while.

while (reader.Read())

Внутри этого цикла мы создаем один экземпляр Airport для каждой строки. Код похож на тот, что мы делали вручную, и я выделил для вас важные части. Мы хотим иметь свежий аэропорт для каждой строки. Это делается с помощью первой строки ниже.
Вместо того, чтобы устанавливать значения вручную, мы используем переменную reader, которая позволяет нам указывать имя-столбца, заключенные в квадратные скобки, чтобы получить значение столбца для текущей строки. В нашем случае мы знаем из нашей предыдущей работы с SQL, что все столбцы имеют тип varchar. Читатель фактически возвращает общие объектные значения, и поэтому нам нужно преобразовать их в строку. Это означает, что мы явно говорим компилятору: «Даже если вы получите значение типа object, я уверен, что это строка».

Мы были очень грязными и также сохранили широту и долготу в виде строк в базе данных. Преобразование в число с помощью Double.Parse возможно, но тогда нам придется иметь дело с пустыми значениями, пробелами, десятичными разделителями и т. Д. Поскольку мы не используем эту информацию прямо сейчас, мы снова работает грязно и вручную установите значение 0.

Последнее, что нужно сделать внутри цикла, - это добавить этот вновь созданный аэропорт в список, который мы определили в начале этого метода. И, конечно же, нам нужно вернуть список в самом конце метода.

Airport myAirport = new Airport();
myAirport.airport = (string)reader["airport"];
myAirport.city = (string)reader["city"];
myAirport.country = (string)reader["country"];
myAirport.iata_code = (string)reader["iata_code"];
myAirport.latitude = 0;
myAirport.longitude = 0;
myAirport.state = (string)reader["state"];
airports.Add(myAirport);

Я знаю, что вы хотите это проверить, но подождите еще минуту или две. Осталось кое-что, и все готово. Нам нужно удалить все жестко запрограммированные элементы из метода OnGet и вместо этого заполнить переменную airport, используя нашу блестящую новую функцию:

public void OnGet()
{
  this.airports = GetAirports();
}

Теперь ваш файл должен выглядеть, как показано ниже. Полная версия также находится в моем репозитории на github (https://github.com/martinhorvath/com.primebird.net5webapp/blob/feature/read-from-db/Pages/Index.cshtml.cs)

Теперь перейдите к Index.cshtml в последний раз. Здесь нам нужно настроить код так, чтобы мы создавали один блок для каждого аэропорта в переменной airport, и мы делаем это следующим образом:

@foreach (Airport airport in Model.airports)
{
  <hr />
  <div class="text-center">
    <h1 class="display-5">@airport.airport</h1>
    <p>This airport is in @airport.country 
       and identified by iata code @airport.iata_code
    </p>
  </div>
}

Объедините весь блок div, который мы создали изначально, в цикл foreach, которому предшествует символ @, который вводит код C # внутри cshtml. В цикле foreach мы можем определить тип объекта как первый аргумент в круглых скобках. Второй аргумент - это имя этой переменной. И, наконец, этот аэропорт можно найти в Model.airports. Вы помните, что все переменные внутри IndexModel доступны в cshtml, верно?

По визуальным причинам я добавил ‹hr /› перед текстовым блоком, чтобы создать горизонтальную линейку. Переменные, которые мы использовали раньше, @ Model.airport, изменены: Model больше не требуется, поскольку мы ссылаемся на airport-variable, определенную внутри foreach.

Теперь также добавьте эту строку в верхнюю часть файла (НЕ над «страницей»), чтобы в этом файле также находился тип Airport:

@using Entities

Вот и все, мы готовы к тестированию, если ваш файл выглядит так, как показано ниже. Полная версия также находится в моем репозитории на github (https://github.com/martinhorvath/com.primebird.net5webapp/blob/feature/read-from-db/Pages/Index.cshtml)

Запустите отладчик и наслаждайтесь красотой вашего списка аэропортов, читайте в реальном времени из своей базы данных.

Сделайте изменения этого приложения совместимыми с контейнерной БД

Даже если это приложение теперь работает локально, это не значит, что это так для контейнерной установки. Вы уже заметили важные части?

var connString = "Host=localhost;Username=postgres;Password=newton243;Database=postgres";

Когда это выполняется в контейнере, возникает исключение подключения, поскольку локальный хост (то есть «этот контейнер») не будет размещать базу данных. Вместо этого нам нужно подключиться к правильному контейнеру и открытому порту.

Давайте использовать переменную среды для того, что мы можем определить при последующем запуске контейнера. Этого можно добиться, заменив строку подключения следующим:

var connString = Environment.GetEnvironmentVariable("primebird_connectionstring");

Чтобы проверить это также локально, если у вас нет этой переменной, вы можете отредактировать файл launch.json, который является конфигурацией вашего режима отладки / запуска. Вы должны найти там свойство с именем env, которое уже включает переменную с именем ASPNETCORE_ENVIRONMENT. Мы добавим пользовательский со строкой подключения, как показано на скриншоте ниже:

Сеть Docker

Еще одна вещь, с которой мне нужно вас познакомить, - это сеть докеров. Docker управляет собственными сетями и назначает IP-адреса подключенным контейнерам. То же самое происходит, когда вы подключаете кабель Ethernet к компьютеру или когда подключаетесь к Wi-Fi. Сети, созданные докером, можно проверить с помощью следующего:

docker network ls

Контейнеры могут быть добавлены к одной или нескольким сетям во время запуска и даже когда они включены. Чтобы проверить подробную информацию о сети, используйте следующую команду (где bridge обозначает имя сети):

docker network inspect bridge

Там вы можете увидеть IP-диапазон, прикрепленные контейнеры (в данном случае ни одного) и т. Д. Еще один важный факт, который следует знать, это то, что контейнеры докеров могут связываться друг с другом по имени контейнера, если они присоединены к одному и тому же сеть. Это означает, что мы можем использовать имя db-контейнера в строке подключения нашего веб-приложения!

Чтобы вещи были разделены, мы сделаем следующее:

  • Создайте выделенную сеть в докере для нашего веб-приложения и его базы данных.
docker network create -d bridge webapp-network
  • Прикрепите db-контейнер
docker network connect webapp-network webappdb

Последний параметр команды docker network connect - это имя контейнера. webappdb был создан в этой статье. Проверьте имена своих контейнеров с помощью docker ps -a!

Если вы теперь повторите предыдущие команды docker network ls и docker network inspect, вы должны увидеть новую сеть и хотя бы один прикрепленный контейнер (webappdb) (если контейнеры Бег!). Если они остановлены, сначала запустите их с помощью docker start ‹containerName›! В моем случае веб-контейнер тоже прикреплен, но сейчас он вам не нужен. Но это также не повредит, если вы захотите потренироваться.

Все готово, и мы готовы обновить контейнер aspnet-webapp другой сборкой, как мы это делали в первой части. CD в ​​корневой каталог вашего приложения (где находится Dockerfile) или используйте терминал внутри VisualStudioCode для выполнения команды публикации, чтобы скомпилировать последние изменения:

dotnet publish --configuration Debug

Затем создайте новый док-контейнер:

docker build -t aspnetcore-webapp .

И убедитесь, что изображение было обновлено. Мой говорит 4 минуты назад на картинке ниже.

docker image ls

Теперь мы создаем еще один контейнер aspnetwebapp-ct2 (или любое другое имя, которое вам нравится) с немного отредактированной командой, чтобы предоставить строку подключения к базе данных в качестве переменной среды. Чтобы оба веб-контейнера работали параллельно, я решил сопоставить локальный порт 5009 с портом контейнера. Я переименовал контейнер в aspnetwebapp-ct2 и в качестве хоста использовал имя db-контейнера. Вся строка подключения заключена в двойные кавычки, чтобы избежать ошибок команды.

docker run -d -p 5009:5001 --name aspnetwebapp-ct2 -e ASPNETCORE_Kestrel__Certificates__Default__Password=<passwordForTheCertificate> -e ASPNETCORE_Kestrel__Certificates__Default__Path=/opt/webapp/devcert.pfx -e primebird_connectionstring="Host=webappdb;Username=postgres;Password=newton243;Database=postgres" --mount type=bind,source=<dockersharepath>,target=/opt/webapp aspnetcore-webapp

Убедитесь, что контейнер успешно запущен с помощью docker ps -a, и если это так, вам просто нужно подключить его к ранее подключенной сети. Хотите увидеть ошибку? Просмотрите свой веб-сайт перед подключением его к сети;) Он доступен по адресу https: // localhost: 5009

docker network connect webapp-network aspnetwebapp-ct2

Теперь перейдите на сайт https: // localhost: 5009 и снова насладитесь красотой списка аэропортов. Который теперь извлекается из другого контейнера.

Чего вы достигли…

Вы так далеко читали! Поздравляю, вы отлично справились и узнали

  • как развернуть базу данных postgres в докер-контейнере
  • как импортировать данные в базу данных sql
  • как читать данные из sql внутри приложения .net
  • как создавать сети докеров и подключать контейнеры
  • как использовать переменные среды, предоставляемые докером, в веб-приложении .net

Но вы также должны знать, что это всего лишь самая базовая реализация, и теперь откройте свой разум, поскольку есть еще очень много того, что нужно исследовать. Стоит взглянуть на EntityFramework или NHibernate, чтобы использовать уровень абстракции базы данных. Вы можете изучить такие аспекты безопасности, как SQL-инъекция, изоляция контейнера,… просто чтобы предложить несколько идей.

И последнее, но не менее важное ... следите за моим профилем, если вам понравилась эта статья. Я продолжу это путешествие :-)

Исправление проблем

  • Ищете окончательный код? Это здесь: https://github.com/martinhorvath/com.primebird.net5webapp/tree/feature/read-from-db-dockerized
  • Всегда дважды проверяйте имена контейнеров и убедитесь, что они работают.
  • Убедитесь, что в большинстве команд нет разрыва строки, даже если он выглядит так, как в представлении здесь
  • Отказано в разрешении при выполнении команд docker…? Возможно, вам понадобится sudo, если вы работаете в Linux.
  • Проблемы с подключением к базе данных? Попробуйте отключить брандмауэр, чтобы не было заблокированных портов.