reactjs - 如何通过 docker 连接 API 和 React App

标签 reactjs docker api

我有一个基于 PHP (lumen) 的 API 和一个基于 React 的电子商务。
两者的工作都很好。当我尝试通过 Docker 使其工作时,问题就来了。
我想部署仅运行一个命令的整个应用程序。
问题是 react 应用程序没有与 API 连接。
我在这篇文章中尝试了@Suman Kharel 的回答
Proxying API Requests in Docker Container running react app
但它不起作用。有谁知道我怎样才能解决它?
这是我在 bitbucket 上的 repo。
https://bitbucket.org/mariogarciait/ecommerce-submodule/src/master/
希望有人知道我做错了什么。
谢谢

最佳答案

使用 docker-compose 仅​​用于测试目的或非常有限的生产基础设施。最好的方法是将您的工件分别放在不同的主机中。
请阅读这些以了解一些要点:

  • one service per container
  • docker ip vs localhost
  • docker : links/networks vs variables

  • 当您使用 docker-compose 时,所有服务都部署在同一台机器上,但每个服务都在一个容器中。并且只有一个进程在容器内运行。
    因此,如果您进入一个容器(例如 nodejs 中的 Web)并列出进程,您将看到如下内容:
    nodejs .... 3001
    
    并进入另一个容器,如数据库 postgres:
    postgres .... 5432
    
    所以,如果nodejs web需要连接数据库,从内部,必须需要ip来代替本地主机 postgress 数据库,因为在 nodejs 容器内部,只有一个进程在本地主机中运行:
    localhost 3001
    
    所以,使用 localhost:5432不会在 nodejs 容器内工作。解决办法是使用postgres的ip代替localhost:10.10.100.101:5432解决方案
    当我们有多个容器 (docker-compose) 并且它们之间存在依赖关系时,docker 建议我们:
  • Deprecated: container links
  • Docker networks

  • 总而言之,通过这些功能,docker 创建了一种“特殊网络”,您的所有容器都可以在其中安静地离开,而不会受到 ips 的影响!
    带有 host.docker.internal 的 Docker 网络
    仅用于测试、快速部署或在非常有限的生产环境中,您可以使用最新版本的 docker-compose(1.29.2) 和 docker 中的新功能。
    在 docker-compose 的末尾添加这个
    networks:
      mynetwork:
        driver: bridge
    
    如果某些容器需要主机 ip,请使用 host.docker.internal 而不是ip
    environment:
      - DATABASE_HOST=host.docker.internal
      - API_BASE_URL=host.docker.internal:8020/api
    
    最后在使用 的容器中host.docker.internal 添加这个:
    extra_hosts:
      - "host.docker.internal:host-gateway"
    
    只需将此添加到您的所有容器中
    networks:
      - mynetwork     
    

    Note: This was tested on ubuntu, not on mac or windows, because no bodies deploy its real applications on that operative systems


    环境变量方法
    在我看来,Docker 链接或网络是一种幻觉或欺骗,因为这仅适用于一台机器(开发或登台),隐藏了我们和其他复杂主题的依赖关系,当您的应用程序离开您的笔记本电脑并转到您的准备好供您的用户使用的真实服务器。
    无论如何,如果您将 docker-compose 用于开发人员或实际目的,这些步骤将帮助您管理容器之间的 ip:
  • 获取您机器的本地 ip 并存储在一个 var 中,例如 $MACHINE_HOST 在像这样的脚本中:startup.sh
  • 从 docker-compose.json 中删除链接或网络
  • 使用 $MACHINE_HOST 引用容器中的另一个容器。

  • 例子:
    db:
      image: mysql:5.7.22
      container_name: db_ecommerce
      ports:
        - "5003:3306"
      environment:
        MYSQL_DATABASE: lumen
        MYSQL_ROOT_PASSWORD: ${DATABASE_PASSWORD}
    
    api-php:
      container_name: api_ecommerce
      ports:
        - "8020:80"
        - "445:443"
      environment:
        - DATABASE_HOST=$MACHINE_HOST
        - DATABASE_USER=$DATABASE_USER
        - DATABASE_PASSWORD=$DATABASE_PASSWORD
        - ETC=$ETC
    
    web-react:
      container_name: react_ecommerce
      ports:
        - 3001:3000
      environment:
        - API_BASE_URL=$MACHINE_HOST:8020/api
    
  • 最后运行你的startup.sh,它包含变量和经典docker-compose up -d

  • 同样在您的 react 应用程序中,使用 package.json 中的 var 代替代理读取您的 api 的 url:
    process.env.REACT_APP_API_BASE_URL
    
    查询 this了解如何从 react 应用程序读取环境变量。
    在这里您可以找到更详细的使用步骤 MACHINE_HOST 变量及其用途:
  • https://stackoverflow.com/a/57241558/3957754

  • 建议
  • 在 docker-compose.json 文件中使用变量而不是硬编码值
  • 分离您的环境:开发、测试和生产
  • 构建只是在开发阶段。换句话说,不要使用 构建 在你的 docker-compose.json 中。也许对于本地发展可能是另一种选择
  • 对于测试和生产阶段,只需运行在开发阶段构建和上传的容器(docker 注册表)
  • 如果您在 React 应用程序中使用代理或环境变量读取 api 的 url,则您的构建将仅在一台机器上运行。如果您需要在多个环境之间移动它,例如:测试、暂存、uat 等,您必须执行新构建,因为 react 中的代理或环境变量是在您的 bundle.js 中硬编码的。
  • 这不仅仅是 react 的问题,也存在于 angular、vue 等中:检查 限制 1:每个环境都需要单独的构建 this page 中的部分
  • 您可以评价https://github.com/utec/geofrontend-server如果适用于您,解决之前解释的问题(以及其他问题,例如身份验证)。
  • 如果您的计划是向真实用户展示您的网络,则 web 和 api 必须具有不同的域,当然还有 https。例子
  • eCommerce.zenit.com 用于您的 React 应用程序
  • api.zenit.com 或 ecomerce-api.zenit.com 用于您的 php api

  • 最后,如果您想避免这种令人头疼的基础设施复杂性问题,并且您没有 DevOps 和系统管理员团队,您可以使用 heroku、 digital ocean 、openshift 或其他类似的平台。几乎所有这些都与 docker 兼容。因此,您只需要对每个包含 Dockerfile 的 repo 执行 git push。该平台将解释您的 Dockerfile,部署并为您分配一个现成的 http 域用于测试或一个很酷的域用于生产(在获取域和证书之前)。
  • 关于reactjs - 如何通过 docker 连接 API 和 React App,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63136530/

    相关文章:

    javascript - 解析 CSV 而不下载/保存

    javascript - 对于 GraphQL,声明一个与 GraphQL "class"没有任何明显差异的支持模型 "Type"有什么好处或必要性?

    javascript - componentWillMount 中的多个 fetch 语句

    docker - 在无人机上运行时无法在 Dockerized Phoenix App 上找到 Hex

    javascript - 无法从 JSON 获取嵌套对象

    javascript - 打开下拉菜单时如何更改 Material UI Select 组件(在轮廓模式下)的轮廓颜色(当前为蓝色)

    python - manage.py startapp从Docker内部创建只读文件

    shell - 设置环境变量,同时引用另一个

    ios - NSURLSessionDownloadTask API 调用 Swift 语法说明

    java - 是否有一种官方方法可以使用 AccountManager 帐户在 Android 上对 Google Data API 进行身份验证?