Вызов API в контейнере реакции docker-compose в контейнер django с использованием имени службы

#reactjs #docker #docker-compose #microservices #devops

Вопрос:

У меня есть докер-композиция, содержащая приложение react и другой контейнер django. Они находятся в одной сети, поэтому, когда я пытаюсь сделать запрос curl из контейнера react на один из сервисов django, используя имя службы, которое он работает, но в веб-приложении он не работает, и он сказал :

POST http://backend-account:8000/api/auth/login/ net::ERR_NAME_NOT_RESOLVED

это моя докерская композиция :

 version: "3.9"
services:
  db-account:
    restart: always
    container_name: ctr-db-account-service
    image: mysql:8
    environment:
      - MYSQL_DATABASE=dtp_db
      - MYSQL_USER=admin
      - MYSQL_PASSWORD=ictf
      - MYSQL_HOST=db
      - MYSQL_PORT=3306
      - MYSQL_ROOT_HOST=%
      - MYSQL_ROOT_PASSWORD=root
    volumes:
      - account-data:/var/lib/mysql
    networks:
      - dtp-network

  db-stream:
    restart: always
    container_name: ctr-db-stream-service
    image: mysql:8
    environment:
      - MYSQL_DATABASE=dtp_db
      - MYSQL_USER=admin
      - MYSQL_PASSWORD=ictf
      - MYSQL_HOST=db
      - MYSQL_PORT=3306
      - MYSQL_ROOT_HOST=%
      - MYSQL_ROOT_PASSWORD=root
    volumes:
      - stream-data:/var/lib/mysql
    networks:
      - dtp-network

  backend-account:
    restart: always
    container_name: ctr-account-service
    command:
      # bash -c "python check_db.py --service-name db --ip db --port 3306 amp;amp;
      bash -c "sleep 20 amp;amp;
      python manage.py migrate amp;amp;
      python manage.py runserver 0.0.0.0:8000"
    env_file:
      - ./dtp-account-management-app/account_management/.env
    build:
      context: ./dtp-account-management-app/account_management/
      dockerfile: Dockerfile
    expose: 
      - 8000
    ports:
      - "8080:8000"
    depends_on:
      - db-account
    links:
      - db-account
    networks:
      - dtp-network

  backend-stream:
    restart: always
    container_name: ctr-stream-service
    command:
      # bash -c "python check_db.py --service-name db --ip db --port 3306 amp;amp;
      bash -c "sleep 20 amp;amp;
      python manage.py migrate amp;amp;
      python manage.py runserver 0.0.0.0:7000"
    env_file:
      - ./dtp-stream-management-app/stream_management/.env
    build:
      context: ./dtp-stream-management-app/stream_management/
      dockerfile: Dockerfile
    expose: 
      - 7000
    ports:
      - "7000:7000"
    depends_on:
      - db-stream
    links:
      - db-stream
    networks:
      - dtp-network

  frontend:
    restart: always
    command: npm start
    container_name: ctr-frontend-service
    build:
      context: ./dtp-frontend-app/
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    stdin_open: true
    depends_on:
      - backend-account
      - backend-stream
    links:
      - backend-stream
      - backend-account
    networks:
      - dtp-network

networks:
  dtp-network:
    driver: bridge

volumes:
  account-data:
    driver: local
  stream-data:
    driver: local
 

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

 /react # curl -i -X GET --url http://backend-account:8000/api/auth/login/
HTTP/1.1 200 OK
Date: Mon, 13 Sep 2021 11:25:06 GMT
Server: WSGIServer/0.2 CPython/3.9.6
Content-Type: application/json
Vary: Accept, Origin
Allow: POST, OPTIONS
X-Frame-Options: DENY
Content-Length: 40
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
 

Ответ №1:

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

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

Затем вам нужно использовать IP-адрес сервера или доменное имя, которое вы настроили, в своем интерфейсном коде, чтобы перейти на серверную часть Django.

Поскольку вы уже опубликовали порты своих бэкэндов, 8080:8000 и 7000:7000 вы можете использовать эту службу на своем IP-адресе сервера , если позволяет брандмауэр.

Например, используйте один из них в своем интерфейсном коде.

 http://<your-server-ip>:8080
# or
http://<your-server-ip>:7000
 

Тем не менее, я бы посоветовал приобрести домен и установить DNS-запись, указывающую на ваш сервер. Тогда вы также могли бы предоставить надлежащий SSL-сертификат, шифрующий трафик.

Кстати, если вы хотели только внутренней связи между службами с docker, то вам не нужно публиковать порты, как вы это делали. Это может привести или не привести к проблемам безопасности. Например, в вашей базе данных нет опубликованных портов, и серверная часть все еще может подключаться. Но, как я уже сказал, это скорее случайный побочный факт, чем часть реального ответа. Чтобы решить вашу проблему, вам нужно сделать то, что я описал выше.