使用服务名称在 docker 中调用 API-compose React 容器到 django 容器

Calling API in a docker-compose React container to django container using service name

我有一个 docker 组合,其中包含一个 React 应用程序和其他 Django 容器。它们在同一个网络中,所以当我尝试使用服务名称从 React 容器向其中一项 Django 服务发出 curl 请求时,它可以工作,但在 Web 应用程序中它不起作用,它说:

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

这是我的 docker 撰写 :

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 &&
      bash -c "sleep 20 &&
      python manage.py migrate &&
      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 &&
      bash -c "sleep 20 &&
      python manage.py migrate &&
      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 # 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

您的网络应用程序 (react) 最终 运行 在用户的浏览器中,而不是在容器中。那时它们不在同一个 docker 网络中,使用服务名称将无法像在容器中使用 curl 时那样工作。

所以你需要在你的服务器上公开你的服务,这样在家里自己机器上的用户使用他们的浏览器就可以发出网络请求。

然后你需要在你的前端代码中使用你设置的服务器IP地址或域名来访问Django后端。

由于您已经发布了后端 8080:80007000:7000 的端口,如果您的防火墙允许,您可以在您的服务器 IP 上访问该服务。

例如,在您的前端代码中使用其中一个。

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

也就是说,我建议购买一个域并设置一个指向您的服务器的 DNS 记录。然后您还可以提供适当的 SSL 证书,加密流量。

附带说明一下,如果您只想使用 docker 在服务之间进行内部通信,那么您不需要像以前那样发布端口。这可能会也可能不会导致安全问题。例如,您的数据库没有发布端口,后端仍然可以连接。但正如我所说,这更像是一个随机的附带事实,而不是实际答案的一部分。要解决您的问题,您需要执行我上面描述的操作。