从服务器端(从另一个容器)引用 Docker 容器,并从客户端(浏览器)使用相同的 URL

Referencing Docker container from server-side (from another container) AND from client-side (browser) with same URL

我有两个 docker 个容器 frontenddata-service

frontend 正在使用 NextJS,这只是相关的,因为 NextJS 有一个名为 getInitialProps() 的方法,它可以是服务器上的 运行,也可以是 运行 在访问者的浏览器(我无法控制这个)。

getInitialProps() 中,我需要调用一个 API 来获取页面的数据:

fetch('http://data-service:3001/user/123').then(...

在服务器上调用时 API returns 很好,因为我的前端容器可以访问内部 docker 网络,因此可以使用主机名引用数据服务http://data-service.

然而,当在客户端调用它时,它失败了(显然),因为 Docker 现在公开为 http://localhost,我不能再引用 http://data-service

如何配置 Docker 以便我可以将 1 URL 用于两种用例。如果可能的话,我宁愿不必在我的 NextJS 代码中弄清楚我所处的环境。

如果看到我的 docker-compose 有用,我将其包含在下面:

version: '2.2'
services:
  data-service:
    build: ./data-service
    command: npm run dev
    volumes:
      - ./data-service:/usr/src/app/
      - /usr/src/app/node_modules
    ports:
      - "3001:3001"
    environment:
      SDKKEY: "whatever"
  frontend:
    build: ./frontend
    command: npm run dev
    volumes:
      - ./frontend:/usr/src/app/
      - /usr/src/app/node_modules
    environment:
      API_PORT: "3000"
      API_HOST: "http://catalog-service"
    ports:
      - "3000:3000"

这个 post 中描述了我找到的最优雅的解决方案:

示例实现:

next.config.js中:

module.exports = {
  serverRuntimeConfig: {
    // Will only be available on the server side
    URI: 'your-docker-uri:port'
  },
  publicRuntimeConfig: {
    // Will be available on both server and client
    URI: 'http://localhost:port'
  }
}

pages/index.js中:

import getConfig from 'next/config';
const { serverRuntimeConfig, publicRuntimeConfig } = getConfig();
const API_URI = serverRuntimeConfig.apiUrl || publicRuntimeConfig.apiUrl;

const Index = ({ json }) => <div>Index</div>;

Index.getInitialProps = async () => {
       ...
       const res = await fetch(`${API_URI}/endpoint`);
       ...
}