Следите за тем, чтобы вы использовали localhost при использовании Docker и Docker Compose.

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

У меня есть веб-сайт ASP.NET Core, который подключается к API. Веб-сайт использует прокси-класс для вызова API, который подключается к базовому URL-адресу API, а затем создает вызовы к различным конечным точкам API от имени веб-сайта.

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

Для локального разработчика и тестирования рассматриваемые URL-адреса для веб-сайта и API следующие:

  • Веб-сайт: https: // localhost: 4222 (работает в IIS Express)
  • API: https: // localhost: 5555 (работает в Docker)

Теперь, когда я запускаю веб-сайт в Visual Studio с помощью IIS Express, все становится просто ужасно. Веб-сайт вызывает прокси, прокси вызывает контейнер API Docker через порт 5555, и все работает без сбоев.

Однако, пытаясь перенести веб-сайт на Docker и Docker Compose, я создал файл Docker и Docker Compose, а затем запустил свой веб-сайт. Прокси-класс API веб-сайта продолжал отключать это сообщение об ошибке каждый раз, когда я пытался вызвать какие-либо конечные точки API.

Cannot assign requested address

Какого черта?

Контекст контейнера Docker: localhost НЕ является вашей рабочей станцией

Теперь это сообщение об ошибке не было моим прокси-классом. На это жаловался Докер, и не зря.

Важно понимать использование термина «локальный хост» при работе с Docker на вашей рабочей станции. Вот диаграмма того, как все это работает при запуске веб-сайта на моей рабочей станции под IIS Express.

Как видите, моя рабочая станция - localhost. Любые и все вызовы localhost будут направляться на мою рабочую станцию ​​для разрешения DNS (все машины разрешают себя на localhost) и соответственно маршрутизироваться.

Веб-сайт, работающий на моей рабочей станции под IIS Express, видит https: // localhost: 5555 (API) как отдельный URL-адрес на localhost и соответственно запрашивает этот URL-адрес. Это потому, что мой веб-сайт работает в контексте моей рабочей станции. Он не знает, что такое localhost, но знает, что эту проблему решит основная рабочая станция.

Не имеет значения, работает ли API в IIS Express или в качестве контейнера Docker на моей рабочей станции, до тех пор, пока правильные порты отображаются и отображаются в API, веб-сайт будет использовать рабочую станцию ​​для разрешения маршрута к localhsot: 5555 .

Теперь давайте посмотрим, что происходит, когда я запускаю свой веб-сайт как контейнер Docker.

Теперь, когда мой веб-сайт работает внутри контейнера Docker, ИТ превратился в собственный маленький локальный хост. У него нет контекста моей рабочей станции, и поэтому он пытается разрешить сам localhost: 5555, но, конечно, не может. Ясно, что я не сопоставил порт 5555 на своем веб-сайте, так как это порт, принадлежащий моему API, но контейнер не знает этого, поэтому он пытается перезвонить самому себе через порт 5555, и мы получаем 'Невозможно назначить запрошенный адрес '.

Исправлено: контейнеры совместно используют сеть Docker.

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

  1. Ваши контейнеры Docker не определены в центральном источнике, то есть они находятся в разных проектах / репозиториях.
  2. Вам не нужен центральный файл для создания докеров, чтобы объединить их в общую сеть для создания сообщений.
  3. Вы хотите использовать инструменты отладки Visual Studio в обоих контейнерах (два запущенных экземпляра Visual Studio, один для веб-сайта и один для API), чтобы вы могли отлаживать оба одновременно.

Предположим, это так, и посмотрим, что вам нужно сделать, чтобы дать им возможность общаться. ПРИМЕЧАНИЕ. Даже если вы НЕ используете Visual Studio, вы найдете эти инструкции полезными.

Создайте внешнюю сеть докеров

Мы создадим сеть докеров, в которую будут добавлены оба наших контейнера. Это легкая часть

docker network create -d bridge my-network

Добавьте ссылку на внешнюю сеть к нашим двум файлам Docker-Compose

Добавьте ссылку на сеть как на веб-сайт, так и на docker-compose.override.yml API, как показано ниже:

Если присмотреться, можно заметить две интересные вещи:

  1. Мы передаем в контейнер нашего веб-сайта переменную среды, которая является URL-адресом нашего контейнера API на основе атрибута container_name API. Эта переменная среды передается в прокси-класс API моего веб-сайта в качестве базового URL-адреса моего API.
  2. Порт для API, используемый в этой переменной среды, - это не 5555, а 5000. Причина в том, что сопоставление портов в файле API docker-compose используется для сопоставления порта контейнера по умолчанию 5000 с портом 5555 рабочей станции. Поскольку наше веб-приложение и наш API теперь находятся в одной сети Docker, они вообще не заботятся о хост-машине (рабочей станции). Мы можем просто использовать выставленные порты по умолчанию.

Запустите наши контейнеры

Теперь я сначала запускаю контейнер API в Visual Studio (или через интерфейс командной строки docker-compose), а затем делаю то же самое для веб-сайта.

Престо! Контейнер Docker моего веб-сайта запускается в сети My-Network вместе с Api. Прокси-класс API веб-сайта без проблем подключается к http: // Api: 5000.

Надеюсь это поможет