Как обращаться к серверному хосту с помощью axios, когда интерфейс и сервер находятся в виртуальной сети докеров

Я создаю простой веб-сайт с логином, и мой vue-интерфейс должен получать пользовательские данные из моего nodejs-backend, который подключается к базе данных sql. Я решил использовать для этого docker-compose, и как я понимаю, docker-compose автоматически настраивает сеть для сервисов, которые упомянуты в моем docker-compose.yml.

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

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

Что действительно работает, так это сопоставление порта хоста с моим открытым портом API и использование http://локальный: 5000 в качестве адреса, но это противоречит цели сети докеров.

мой докер-compose.yml:

version: '3.3'

services:
    vue-frontend:
        image: flowmotion/vue-js-frontend
        ports:
            - 8070:80
        depends_on:
            - db-user-api

    db-user-api:
        image: flowmotion/user-db-api
        environment:
            - PORT=5000
        ports:
            - 5000:5000 #only needed if docker network connection can't be established 

рассматриваемые файлы Vue-fontend:

Логин.vue

methods: {
    async login() {
      try {
        const response = await authenticationService.login({
          email: this.email,
          password: this.password
        });
        this.$store.dispatch("setToken", response.data.token);
        this.$store.dispatch("setUser", response.data.user);
        this.$router.push({ path: "/" });
      } catch (error) {
        this.showError = true;
        this.error = error.response.data.error;
      }
    }
  }
};
</script>

аутентификацияService.js

import api from "@/services/api";

export default {
  login(credentials) {
    return api().post("login", credentials);
  }
};

API.js

import axios from 'axios';
import config from '../config/config';
export default () => {
    return axios.create({
        baseURL: config.userBackendServer
    });
};

конфиг.js ()

module.exports = {
    userBackendServer: 'http://cl-dashboard_db-user-api_1:5000' //this doesn't seem to work
};

//using 'http://localhost:5000' works if ports are mapped to host machine.

ожидаемым результатом будет мой бэкэнд, выполняющий поиск sql.

фактический результат: вместо того, чтобы подключаться к моему бэкэнду, мой интерфейс дает мне статус 404, и мой бэкэнд никогда не доступен

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
11
0
10 333
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

точка - ваше приложение vue не находится ни в одном контейнере - оно подается из контейнера в виде файла сценария js в ваш браузер., которая отправляет запросы на серверную часть вашего узла. поскольку ваш браузер никоим образом не находится внутри сети докеров - вы должны использовать внешнее сопоставление портов (localhost:5000 в вашем случае), чтобы получить доступ к серверной части.

дайте мне знать, если у вас есть еще вопросы по этому поводу.

хорошо, это имеет смысл. Итак, для развертывания мне нужно указать обслуживающий IP-адрес/URI с портом, указанным в моем docker-compose.yml? вот так: userBackendServer: 'URItoMyApp:5000'

Flowmotion 30.05.2019 12:54

поместите его как переменную среды в свой файл .env в корневой каталог приложения vue. на данный момент это будет VUE_APP_API_ROOT=http://localhost:500/, и на производстве измените его на имя хоста вашего сервера. предполагается, что ваш серверный производственный контейнер будет сопоставлен с портами хоста по умолчанию (80 и 443), и поэтому вам не нужно указывать какой-либо номер порта.

Efrat Levitan 30.05.2019 19:08

Как насчет привязки портов не к хост-компьютеру, а к данной сети? Например, чтобы избежать прямого доступа к портам служб хосту, я настроил свои контейнеры на использование интерфейса Docker. Теперь я не могу подключить свои сервера к себе. Есть идеи?

Gustavo Silva 13.08.2019 10:33

@GustavoSilva, не могли бы вы рассказать мне больше о том, как выполняется эта «привязка к заданной сети»? Я не уверен, что получил тебя. если это на github, вы можете связать это здесь, и я посмотрю

Efrat Levitan 13.08.2019 12:08

@EfratLevitan, этого нет на GitHub. У меня есть установка, аналогичная описанной выше. Разница в том, что я использую IP-адрес сетевого интерфейса Docker вместо прямой привязки портов служб к хосту. Таким образом, мой порт имеет конфигурацию, аналогичную: порт: - 172.17.0.1:3000:5000

Gustavo Silva 13.08.2019 12:46

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

Efrat Levitan 13.08.2019 13:14

У меня было что-то подобное, да. Я не так легко получаю доступ к контейнерам снаружи. Конфигурация nginx моего хоста соответственно реверсирует прокси. Помните, что я открываю только порты контейнеров для сети докеров.

Gustavo Silva 13.08.2019 19:22

@GustavoSilva, если контейнер недоступен за пределами сети докеров, внешнее приложение не сможет отправлять запросы

Efrat Levitan 13.08.2019 23:04

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

Gustavo Silva 14.08.2019 10:49

@GustavoSilva есть, но внешнее приложение не находится внутри контейнера - оно запускается из браузера. (обратитесь к моему ответу)

Efrat Levitan 14.08.2019 11:18

Да, я следую. Я думаю, мне нужно снова посмотреть на структуру и проверить, что можно сделать. Спасибо за вашу помощь! :+1:

Gustavo Silva 14.08.2019 11:38

@EfratLevitan, как новичок в веб-приложениях, я этого не понимаю: я бы предположил, что передний контейнер является передним для клиента. Таким образом, любой запрос к этому фронту будет делать что-то внутри, что неизвестно пользователю - обращаться к заднему контейнеру и получать ответ. Но здесь происходит то, что пользователь действительно видит, что делает фронт, и может сделать это сам. 1. Это нормально? Разве не уродливо использовать два адреса для одного сайта? 2. Разве для этого сценария не требуется CORS (developer.mozilla.org/en-US/docs/Web/HTTP/CORS), который является хаком? Спасибо!

hudac 11.01.2021 23:11

@hudac 1. внешние приложения работают на стороне клиента, и да, он может просматривать их и манипулировать ими столько, сколько захочет, поэтому любое конфиденциальное действие (например, обращение к БД) должно выполняться с внутренней стороны, а не со стороны клиент. 2. вы можете использовать dev-прокси, чтобы избежать проблем с CORS, вот как это сделать: medium.com/js-dojo/…

Efrat Levitan 12.01.2021 10:27

@EfratLevitan Я не говорю о разработке, я говорю о производстве. Правильно ли работают веб-приложения? например Я захожу на myapp.com, и каждый щелчок, требующий доступа к базе данных (а не только изменения внешнего интерфейса js), скрытно переходит на myapp.back.com? Это правильный способ сделать это? Я думал, что CORS предназначен только для внешнего (не адреса myapp.com) контента.

hudac 12.01.2021 13:23

@hudac Правильно, заголовки CORS не должны использоваться в производстве. Обычная архитектура помещает прокси-сервер (скажем, nginx), который обслуживает внешний файл, и перенаправляет /api/* запросы на внутренний сервер. пример: cli.vuejs.org/guide/deployment.html#docker-nginx

Efrat Levitan 12.01.2021 13:27

@EfratLevitan, да, я читал об этом. Единственное, чего я не понимаю в этом методе, это: 1. конкретно в приложенном вами примере я думаю, что не вижу другого маршрута, кроме root '/'. 2. Если есть другой маршрут - nginx его прямо туда пропускает? или он проходит через мой js-код? Я имею в виду - скажем, у меня есть код, который идет в базу данных, и для каждой записи, которую он получает, он выполняет некоторые манипуляции, а затем красиво показывает это в графическом интерфейсе. Если nginx направит мой запрос не через мой код js, разве я не получу необработанные данные?

hudac 12.01.2021 13:37

Кстати, возможно, этот пример не отражает вариант использования, который я пытаюсь изобразить. В вашей ссылке написано: «Если вы используете Vue CLI вместе с серверной структурой, которая обрабатывает статические ресурсы как часть своего развертывания». Я думаю, что мой вариант использования - db. не статические активы.

hudac 12.01.2021 14:45

хорошо, я нашел этот пример github.com/wkrzywiec/kanban-board/blob/master/kanban-ui/… - обратный прокси-сервер nginx, который перенаправляет внутренние вызовы для /api/*. Спасибо!

hudac 12.01.2021 22:11

Здравствуйте, это старый вопрос, и я столкнулся с той же проблемой. Я понял, о чем идет речь, и я попробую в ближайшее время. Мой вопрос к @EfratLevitan, в какой-то момент вы упомянули: and on production change it to your server hostname. Как это сделать, в том смысле, что вам нужно будет знать свой производственный URL-адрес во время сборки, поскольку после этого вы не можете изменить переменную. Я прав? Или с Vue вы можете сделать это? Поскольку я использую реакцию, я знаю, что после ее создания я не могу изменить это значение.

Vivere 04.05.2021 18:15

@Vivere В производственной среде вы обычно устанавливаете прокси-сервер для получения одного и того же доменного имени для внешнего интерфейса и внутреннего интерфейса (в противном случае вы сталкиваетесь с CORS), поэтому вы можете исключить имя хоста из запрошенного URL-адреса, и по умолчанию браузер будет использовать доменное имя внешнего интерфейса в качестве имени хоста ( например, вы отправляете AJAX на «/api/image1.png») без имени хоста.

Efrat Levitan 05.05.2021 10:04

Другие вопросы по теме