【问题标题】:When to replace localhost with service name in docker?何时用 docker 中的服务名称替换 localhost?
【发布时间】:2021-05-08 19:28:02
【问题描述】:

我有 reactjs 应用程序和 express 应用程序 dockerized。
这是我的 docker-compose.yml 文件:

version: "3"

services:
  client:
    image: react-app
    build: ./client
    ports:
      - "3000:3000"
    volumes:
      - ./client/:/usr/src/app
      - /usr/src/app/node_modules
    container_name: mern-app-client
    environment:
      CHOKIDAR_USEPOLLING: "true"
  server:
    image: express-app
    build: ./server
    ports:
      - "5000:5000"
    volumes:
      - ./server/:/usr/src/app
      - /usr/src/app/node_modules
    container_name: mern-app-server
    environment:
      CHOKIDAR_USEPOLLING: "true"

我有 2 个 dockerfile,每个客户端和服务器中都有 1 个(由节点映像构建)。
运行 docker compose up 后,我在 http://localhost:5000 运行服务器,并在 http://localhost:3000 响应应用程序。
当我在 react 应用程序的 axios/fetch 中将 base_url 作为 http://localhost:5000 时,一切正常。在一些博客(不一定是 mern)中,我看到 localhost 被替换为服务名称。
我尝试了相同的方法并将 react app 中的 base_url 替换为 http://server:5000 但它没有用。
现在我对何时应该替换 base_url 以及为什么需要它的核心概念感到困惑?
如果有人可以解释,我将不胜感激。 感谢您的宝贵时间。

【问题讨论】:

    标签: node.js reactjs docker express mern


    【解决方案1】:

    当您在浏览器中输入 http://localhost:3000 时,浏览器会调用 client 容器,执行 HTTP GET 以检索 Javascript 代码,然后 浏览器 实际运行编码。这是一个关键的区别:来自 React 应用程序的任何 fetch 调用或类似调用都在最终用户的浏览器中运行,而不是在 Docker 中。

    如果来自浏览器的呼叫;它是您的前端应用程序的一部分;或者它来自 Docker 外部,那么您需要使用主机系统的 DNS 名称和第一个发布的 ports: 编号。如果浏览器和容器都在同一个系统上运行,你可以使用localhost;如果 Docker 在 VM 中运行(可能在较旧的 Docker Toolbox 设置上),则需要 VM 的 IP 地址。

    +-------------+                         +-----------------------+
    | Browser     |  http://localhost:3000/ | client:               |
    |   React app | ----------------------> |   ports: ['3000:...'] |
    +-------------+                         +-----------------------+
    

    一个容器也可以直接相互调用。也许client 容器会调用server 作为在将页面发送回浏览器之前预渲染页面的一部分;也许server 有一个支持db。在这种情况下,您可以使用 Compose 服务名称作为主机名,以及服务器进程正在侦听的任何端口。 ports: 不是必需的,如果存在则被忽略。

    +----------+                      +-------------------------+
    | server:  |  postgres://db:5432/ | db:                     |
    |          | -------------------> |   # ports: ['...:5432'] |
    +----------+                      +-------------------------+
    

    Docker 文档中的Networking in Compose 进一步描述了此设置。一般不需要显式指定container_name:networks:; Compose 为您提供了这些东西的合理工作默认值。

    对于需要为应用程序本身和单独的 API 服务器配置 URL 的基于浏览器的应用程序,一个好的做法是将反向代理设置为容器。这可能是 Nginx 之类的东西,或者是纯开发环境中 Webpack 的代理服务器。由于代理在两个容器之间进行调用,因此您将使用 Docker 内部 URL http://server:5000 为后端配置它。这意味着浏览器内代码和后端 API 都位于同一主机和端口上,因此您可以使用仅路径相对 URL /api/...,绕过使用哪个主机和端口的问题。

    【讨论】:

    • 所以现在我们不能用服务名称替换 localhost 因为浏览器在 docker 之外并且它不知道服务名称?但是部署后我们可以用IP地址或域名替换它吗?
    • 如果我们使用 nginx 反向代理,react 应用中的 axios 基本 URL 是什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-27
    • 2020-12-19
    • 1970-01-01
    • 1970-01-01
    • 2020-02-18
    相关资源
    最近更新 更多