什么时候用 docker 中的服务名称替换 localhost?

When to replace localhost with service name in docker?

我已经 docker 化了 reactjs 应用程序和 express 应用程序。
这是我的 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 个 docker 文件,每个客户端和服务器各 1 个(从节点映像构建)。
运行 docker 完成后,我在 http://localhost:5000 有服务器 运行 并在 http://localhost:3000 有反应应用程序。
当我在 React 应用程序的 axios/fetch 中将 base_url 作为 http://localhost:5000 时,一切正常。在一些博客中,不一定是 mern,我看到 localhost 被替换为服务名称。
我尝试了同样的方法并将 React 应用程序中的 base_url 替换为 http://server:5000 但它没有用。
现在我对什么时候应该更换 base_url 以及为什么需要它的核心概念感到困惑?
如果有人可以解释,我将不胜感激。 谢谢你的时间。

当您转到浏览器并在其中键入 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 服务器配置 URLs 的基于浏览器的应用程序,一个好的做法是将反向代理设置为一个容器。这可能是 Nginx 之类的东西,或者在纯开发环境中 Webpack 的代理服务器。由于代理在两个容器之间进行调用,因此您需要为后端配置 Docker-internal URL http://server:5000。这意味着浏览器内代码和后端 APIs 都在同一主机和端口上,因此您可以使用仅路径相对 URL /api/...,绕过使用哪个主机和端口的问题。