Следите за тем, чтобы вы использовали 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 было самым простым способом сделать это. Это особенно актуально, если:
- Ваши контейнеры Docker не определены в центральном источнике, то есть они находятся в разных проектах / репозиториях.
- Вам не нужен центральный файл для создания докеров, чтобы объединить их в общую сеть для создания сообщений.
- Вы хотите использовать инструменты отладки Visual Studio в обоих контейнерах (два запущенных экземпляра Visual Studio, один для веб-сайта и один для API), чтобы вы могли отлаживать оба одновременно.
Предположим, это так, и посмотрим, что вам нужно сделать, чтобы дать им возможность общаться. ПРИМЕЧАНИЕ. Даже если вы НЕ используете Visual Studio, вы найдете эти инструкции полезными.
Создайте внешнюю сеть докеров
Мы создадим сеть докеров, в которую будут добавлены оба наших контейнера. Это легкая часть
docker network create -d bridge my-network
Добавьте ссылку на внешнюю сеть к нашим двум файлам Docker-Compose
Добавьте ссылку на сеть как на веб-сайт, так и на docker-compose.override.yml API, как показано ниже:
Если присмотреться, можно заметить две интересные вещи:
- Мы передаем в контейнер нашего веб-сайта переменную среды, которая является URL-адресом нашего контейнера API на основе атрибута container_name API. Эта переменная среды передается в прокси-класс API моего веб-сайта в качестве базового URL-адреса моего API.
- Порт для API, используемый в этой переменной среды, - это не 5555, а 5000. Причина в том, что сопоставление портов в файле API docker-compose используется для сопоставления порта контейнера по умолчанию 5000 с портом 5555 рабочей станции. Поскольку наше веб-приложение и наш API теперь находятся в одной сети Docker, они вообще не заботятся о хост-машине (рабочей станции). Мы можем просто использовать выставленные порты по умолчанию.
Запустите наши контейнеры
Теперь я сначала запускаю контейнер API в Visual Studio (или через интерфейс командной строки docker-compose), а затем делаю то же самое для веб-сайта.
Престо! Контейнер Docker моего веб-сайта запускается в сети My-Network вместе с Api. Прокси-класс API веб-сайта без проблем подключается к http: // Api: 5000.
Надеюсь это поможет