从服务器端(从另一个容器)和客户端(浏览器)引用具有相同URL的Docker容器

时间:2019-11-28 17:45:30

标签: docker docker-compose next.js

我有两个docker容器frontenddata-service

frontend使用的是NextJS,这仅是相关的,因为NextJS有一个称为getInitialProps()的方法,该方法可以在服务器上运行,也可以在访问者的浏览器中运行(我对此无能为力)

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

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

在服务器上调用此API时,API返回正常,因为我的前端容器可以访问内部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"

1 个答案:

答案 0 :(得分:2)

这篇文章中介绍了我找到的最优雅的解决方案:Docker-compose make 2 microservices (frontend+backend) communicate to each other with http requests

示例实现:

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`);
       ...
}