如何通过 docker 将 API 与 Web SPA 连接起来

Posted

技术标签:

【中文标题】如何通过 docker 将 API 与 Web SPA 连接起来【英文标题】:How to connect API with Web SPA through docker 【发布时间】:2020-11-18 00:51:51 【问题描述】:

我有一个基于 php(流明)的 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/

希望有人知道我做错了什么。

谢谢

【问题讨论】:

【参考方案1】:

如果您想使用 docker 通过单个命令启动所有应用程序,则唯一的选择是 docker-compose

使用 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 需要从内部连接到数据库,则必须需要 postgress 数据库的 ip 而不是 localhost,因为在 nodejs 容器内部,只有一个进程在 localhost 中运行:

localhost 3001

因此,在 nodejs 容器中使用 localhost:5432 将不起作用。解决方案是使用 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

这个到你所有的容器

networks:
  - mynetwork     

如果某些容器需要主机 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"

注意:这是在 ubuntu 上测试的,而不是在 mac 或 windows 上,因为没有机构在该操作系统上部署其真正的应用程序

环境变量方法

在我看来,Docker 链接或网络是一种幻觉或欺骗,因为这只适用于一台机器(开发或登台),对我们隐藏依赖关系和其他复杂主题,当您的应用程序离开您的笔记本电脑和转到准备好供用户使用的真实服务器。

无论如何,如果您将 docker-compose 用于开发人员或实际用途,这些步骤将帮助您管理容器之间的 ip:

获取您机器的本地 ip 并存储在类似 $MACHINE_HOST 的 var 中的脚本中,例如: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 应用程序中,使用 var 代替 package.json 中的代理读取你的 api 的 url:

process.env.REACT_APP_API_BASE_URL

查看this 了解如何从 React 应用中读取环境变量。

这里你可以找到更详细的使用MACHINE_HOST变量的步骤及其使用:

https://***.com/a/57241558/3957754

建议

在 docker-compose.json 文件中使用变量而不是硬编码值 分离您的环境:开发、测试和生产 构建正处于开发阶段。换句话说,不要在 docker-compose.json 中使用 build。也许对于本地发展可能是另一种选择 对于测试和生产阶段,只需运行在开发阶段构建和上传的容器(docker 注册表) 如果您使用代理或环境变量在您的 react 应用程序中读取您的 api 的 url,您的构建将只能在一台机器上运行。如果您需要在多个环境之间移动它,例如:测试、登台、uat 等,您必须执行新构建,因为 react 中的代理或环境变量是硬编码在 bundle.js 中的。 这不仅仅是 react 的问题,也存在于 angular、vue 等中:检查 限制 1:每个环境都需要单独的构建部分 this page 如果申请,您可以评估 https://github.com/utec/geofrontend-server 以解决前面解释的问题(以及其他问题,如身份验证)。 如果您的计划是向真实用户展示您的网站,那么 web 和 api 必须有不同的域,当然还有 https。例子 ecomerce.zenit.com 用于您的 react 应用程序 api.zenit.com 或 ecomerce-api.zenit.com 用于您的 php api 最后,如果您想避免这种令人头疼的基础设施复杂性问题,并且您没有 devops 和 syadmin 团队,您可以使用 heroku、digital ocean、openshift 或其他类似的平台。几乎所有这些都与 docker 兼容。因此,您只需要对每个带有 Dockerfile 的 repo 执行 git push 即可。该平台将解释您的 Dockerfile,部署并为您分配一个可随时使用的 http 域进行测试或一个很酷的域用于生产(事先获得域和证书)。

【讨论】:

以上是关于如何通过 docker 将 API 与 Web SPA 连接起来的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有登录表单的情况下将摘要身份验证与 asp.net web api 和 angular js 一起使用?

我应该使用 Docker 将 Web API 项目(微服务)部署到 Azure Web App [关闭]

Docker初识

Docker入门教程Docker API

Docker初识

docker 架构