Как получить доступ к моему Docker API-контейнеру из моего интерфейсного контейнера? - PullRequest
2 голосов
/ 28 марта 2020

Я новичок в docker и пытаюсь обернуться вокруг сети между контейнерами. Я использую два контейнера, контейнер для моего Node.js API-сервера и контейнер, содержащий мой интерфейсный интерфейс React. Вещи работают хорошо, когда запускают их оба локально. Сервер API предоставляет порт 3001, и с моего сайта React я могу делать вызовы localhost: 3001 / api.

Учитывая, что идея контейнера заключается в том, что он может быть запущен где угодно, как я могу гарантировать, что эти контейнеры две контейнерные службы могут подключаться, когда не работают на локальной машине? Я понимаю, что сети могут быть настроены между docker контейнерами, но это, кажется, неприменимо в этой ситуации, так как реактивный контейнер не делает запрос, а скорее клиент получает доступ к реактивному контейнеру (поэтому localhost теперь будет ссылаться на свою машину вместо моего контейнера API).

Как лучше всего развертывать архитектуру такого типа?

Какие настройки необходимы для гарантии того, что эти контейнеры можно общаться в облачном развертывании, где хост API может динамически генерироваться при развертывании?

Если уместно, я специально обращаюсь к развертыванию в AWS ECS.

Редактировать:

Пакет. json прокси относится только к разработке, так как прокси не вступает в силу в производственной сборке приложения реагирования.

Ответы [ 4 ]

2 голосов
/ 03 апреля 2020

Насколько я понимаю, вы хотите развернуть классическое c двухуровневое приложение, состоящее из интерфейса React и Node.js бэкенда, в Amazon ECS (производственная среда).

Мы установили это для нашего приложения какое-то время go, и я хочу обрисовать в общих чертах решение.

Какова лучшая практика для развертывания этого типа архитектуры?

Это действительно сложный вопрос, так как это также зависит от некоторых характеристик c двух уровней, которые не полностью указаны в вашем вопросе.

Frontend

Первый вопрос, который приходит мне в голову: действительно ли вам нужно запустить интерфейс React из контейнера docker? Это динамический c контент? Если ваше приложение React правильно собрано для работы - как описано в [1] - оно должно быть * c. Преимущество содержимого stati c заключается в том, что его можно легко кэшировать и, следовательно, нет необходимости подавать его из контейнера Docker при производстве. Совершенно противоположный случай: я бы посоветовал подавать контент stati c из контейнера ECS на производстве плохой практикой. Вместо этого вам следует сделать следующее:

  • Создать корзину S3 и развернуть в ней ваши ресурсы * stati c.
  • Необязательно, но настоятельно рекомендуется для производства: используйте какой-то вид Сеть доставки контента (CDN) для эффективного распространения контента и его кеширования. Сервисный ландшафт AWS предоставляет сервис CloudFront для этой цели. Окупается ли это с помощью CloudFront, в свою очередь, зависит от шаблона traffi c вашего приложения. Вы могли бы напрямую обслуживать ресурсы c из своего сегмента S3, что, вероятно, приведет к более высокой задержке, но может быть более рентабельным.

В целом, я бы порекомендовал: если вы планируете для запуска какого-либо серьезного приложения в производство, которое, как ожидается, получит приличную загрузку traffi c и / или разработано как одностраничное приложение (SPA), перенесет ваши ресурсы stati c в S3 и будет обслуживать их через CloudFront .

Backend

Лучшая практика здесь проста: создайте балансировщик нагрузки приложения (ALB), целевую группу и укажите свою целевую группу в службе ECS. ECS обеспечивает интеграцию для AWS Elasti c Балансировка нагрузки. Преимущество использования AWS ALB в том, что для вас автоматически создается запись DNS. [3]

Но что, если мне действительно нужно использовать два контейнера в ECS?

Если вы решите не передавать сторонние ресурсы stati c, поскольку в вашем React есть динамические c детали материал или стоимость решения, описанного выше, не подходит, позвольте мне ответить на ваш второй вопрос:

Какой тип настройки необходим, чтобы гарантировать, что эти контейнеры могут взаимодействовать в облачном развертывании, где хост API может динамически генерироваться при развертывании?

Существует несколько стратегий объединения вещей в ECS. Я полагаю, ваш контейнер React не должен напрямую подключаться к контейнеру Node.js, верно? Поправьте меня, если это предположение неверно. Для меня сценарий выглядит следующим образом:

  1. Клиент -> Docker контейнер 1 "Реагировать" (загрузка, например, index. html)
  2. Клиент (например, с использованием Ajax изнутри индекса. html) -> Docker контейнер 2 "Node.js"

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

Пример:

  • Балансировщик нагрузки приложения с DNS-именем: my-loadbalancer-1234567890.us-west-2.elb.amazon aws .com
  • Сервис A с интерфейсом React
  • Сервис B с Node.js Бэкэнд
  • Целевая группа A, которая перенаправляет трафик c в Сервис A
  • Целевая группа B, которая перенаправляет traffi c в службу B
  • ALB Listener A, который перенаправляет traffi c на порт 80 вашего балансировщика нагрузки в целевую группу A
  • ALB Listener B, который перенаправляет traffi c на порт 8080 вашего балансировщика нагрузки в целевую группу B
  • Дополнительно: настраиваемая запись DNS для вашего собственного домена, которая указывает на балансировщик нагрузки (через запись псевдонима), чтобы предоставить более удобное для пользователя имя в браузере вместо автоматически созданной записи в aws зоне elb.amazon aws .com .

Теперь интерфейс доступен через стандартный порт HTTP вашего балансировщика нагрузки домен и бэкэнд доступны через порт 8080. Вы можете легко активировать SSL на балансировщике нагрузки и использовать вместо него порт 443. [4]
Это позволяет завершать SSL на балансировщике нагрузки вместо вашего docker контейнера - функция, называемая прекращением SSL [5].

Но что, если эти контейнеры должны взаимодействовать друг с другом?

При описанном выше подходе контейнеры могут связываться друг с другом через балансировщик нагрузки приложения. Однако это не идеально, если это сообщение является внутренним по своей природе, поскольку оно направляется через конечную точку балансировки нагрузки publi c. Если мы хотим убедиться, что traffi c не оставляет частную сеть между контейнерами, мы МОЖЕМ * поместить их вместе:

  • создать определение задачи в ECS [ 6] и поместите в него оба контейнера
  • укажите "NetworkMode": "bridge" для задачи
  • укажите ссылку между контейнерами, используя свойство Links в соответствующем определении контейнера (внутри определения задачи)

* снова есть несколько стратегий для достижения этой цели, и я обрисовываю самую простую из известных мне (например, задачи можно также связать друг с другом в частном порядке, используя Service Discovery [7] или режим сети задач * 1088). * awsvp c)

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

ссылки

[1] https://create-react-app.dev/docs/production-build/
[2] https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-load-balancing.html
[3] https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-creating.html#resource -record-наборы-ELB-DNS-имя-процедуры * 110 6 *
[4]
https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html
[5] https://infra.engineer/aws/36-aws-ssl-offloading-with-an-application-load-balancer
[6] https://docs.aws.amazon.com/AmazonECS/latest/developerguide/create-task-definition.html
[7] { ссылка }

0 голосов
/ 04 апреля 2020

Вы должны подготовить ПО C с мин. one su bnet (routetables, gateways, loadbalancer, et c ...). VP C и su bnet будут настроены с диапазоном IP-адресов.

Все экземпляры в Su bnet получат IP-адрес вне своего диапазона, и ваши экземпляры приложения могут общаться с друг с другом. Вы можете предварительно установить фиксированные IP-адреса для своих приложений.

Что касается сине-зеленого развертывания, то оно необходимо для создания (Fargate) ECS-кластера. Соответствующий сервис AWS для контейнера docker равен AWS ECR. Я рекомендую использовать AWS Fargate вместо чистого AWS ECS-экземпляра - меньше денег, больше гибкости.

Информация о VP C и подсетях: https://docs.aws.amazon.com/AmazonECS/latest/userguide/create-public-private-vpc.html

Информация о Фаргейте и Кластере: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-cli-tutorial-fargate.html

0 голосов
/ 01 апреля 2020

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

Я не очень разбираюсь в интерфейсе React Тем не менее, исправьте меня, если я не прав, из того, что я понял, клиентский браузер сначала подключается к интерфейсу пользовательского интерфейса React, который, в свою очередь, предоставляет (или отвечает) веб-страницы с функциями, которые отправляют запросы API на Node.js Сервер API использует встроенный базовый URL и прослушивает порт 3001. В этом случае мне не кажется, что интерфейсный контейнер React UI подключается к контейнеру Node.js API, он просто предоставляет средства клиентскому браузеру для веб-страницы для отправки запросов в нужное место.

Хотя я вроде бы чувствую, что proxy в package.json кажется ключевым, но опять же это не моя область знаний, что действительно нужно сделать, это настройте контейнер React UI для встраивания правильного имени хоста, где размещен API Node JS, чтобы клиентский браузер будет отправлять запросы в правильный пункт назначения. Принимая во внимание то, что вы смогли сделать на локальном компьютере, мне кажется, что конфигурация порта для ваших контейнеров была выполнена правильно, я собираюсь предположить, что они «выставлены». Следовательно, выполнение ваших контейнеров таким же образом на сервере, на котором установлен docker, также будет корректно отображать порты.

Итак, для завершения, в основном, у вас будет сервер, на котором есть c hostname и на нем запущен docker, который, в свою очередь, будет запускать ваши контейнеры и выставлять их порт. Базовая конфигурация c необходима для того, чтобы в контейнере React UI был указан правильный URL-адрес API Node.js, который фактически будет именем хоста publi c вашего сервера (поскольку docker технически прослушивает порты на сервер и отправка их внутрь контейнеров, вот что значит выставлять, больше похоже на переадресацию портов).

0 голосов
/ 29 марта 2020

Первым делом первым. Поскольку сервер - Node.js API и интерфейсный интерфейс React внешнего интерфейса работают в двух разных контейнерах, вам необходимо настроить прокси в пакете . json приложения реакции.

"proxy": "http://<docker_container_name>:3001",

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

Теперь, когда наши службы работают в двух разных контейнерах, поэтому "proxy": "http://localhost:3001", не будет работать, так как это будет прокси-запрос внутри того же внешнего контейнера. Таким образом, нам нужно указать серверу реагирования прокси-запрос на сервер узла, работающий в каком-либо другом контейнере.

Следовательно, docker_container_name фактически является именем контейнера docker, в котором Node.js Сервер API работает.

"proxy": "http://<docker_container_name>:3001",

ПРИМЕЧАНИЕ: Убедитесь, что порт 3001 открыт в контейнере сервера Node.

Что если вы это сделаете не хотите выставлять порт узла сервера ??

Для этого я бы рекомендовал использовать docker -compose. Создайте docker -compose.yml , который будет выглядеть примерно так:

version: "3.7"
services:
  frontend:
    # Add other configuration options for frontend service
    depends_on:
      - backend  
  backend:
    # Add configuration options for backend service

Пожалуйста, обратитесь к этому , чтобы узнать больше о depen_on

...