Docker-compose 使 2 个微服务(前端+后端)通过 http 请求相互通信

Posted

技术标签:

【中文标题】Docker-compose 使 2 个微服务(前端+后端)通过 http 请求相互通信【英文标题】:Docker-compose make 2 microservices (frontend+backend) communicate to each other with http requests 【发布时间】:2019-09-19 04:50:33 【问题描述】:

我有 2 个微服务:带有 next.js 的前端和带有 node.js 的后端,我通过 REST-API 从前端获取数据。

我现在有一个问题,我的 2 个服务似乎没有直接相互通信,问题是,当我在开始时使用 fetch-API 的 getinitialProps() 方法获取数据时,它可以工作。我的服务器端前端通过其服务名称找到后端。但是,当我从客户端向后端发出 http 请求时(例如通过浏览器表单输入)。它再也找不到后端了?这是为什么呢?

这是我的 docker-compose.yml:

version: '3'

services:
  dcbackend:
    container_name: dcbackend
    build:
      context: ./dcbackend
      dockerfile: Dockerfile
    image: dcbackend
    hostname: dcbackend
    ports:
      - '7766:7766'

  dcfrontend:
    container_name: dcfrontend
    build:
      context: ./dcfrontend
      dockerfile: Dockerfile
    image: dcfrontend
    volumes:
      - /app/node_modules
      - ./dcfrontend:/app      
    hostname: dcfrontend
    ports:
      - '6677:6677'

这是我将数据发送到后端的浏览器客户端方法之一(通过浏览器,我的 url 是 http:dcbackend... 所以通常它应该找到后端所在的另一个 docker 环境,但确实如此不是……

    if (environment == 'dev') 
  url_link = `http://localhost:$port`;  
 else 
  url_link = `http://dcbackend:$port`;


let doublettenListe_link = `$url_link/doubletten/`;

 finishDocumentHandler = (anzeige,index) => 
    let thisDocumentID = anzeige.id;
    const requestOptions = 
        method: 'PUT'
    ;

    fetch(doublettenListe_link + thisDocumentID, requestOptions)
    .then((response) =>    
        this.setState(finishSuccess: 'Dubletten in Datenbank eintragen erfolgreich!');
        this.setState(finishFail: '');
        this.processDocumentArray(index);
        console.log(response);
    )
    .catch((error) =>    
        this.setState(finishSuccess: '');  
        this.setState(finishFail : `Error beim Erzeugen des Eintrags! Eintrag wurde nicht in Datenbank gespeichert. Bitte prüfen, ob der Server läuft. $error`);
    ); 
    

我的请求中来自网络选项卡的响应是:

Request URL: http://dcbackend:7766/doubletten/304699981
Referrer Policy: no-referrer-when-downgrade
Provisional headers are shown
Access-Control-Request-Method: PUT
Origin: http://localhost:6677
Referer: http://localhost:6677/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/73.0.3683.103 Safari/537.36

它是否与 docker-configuration、CORS() 或其他任何东西有关?我不能向后端发出客户端 http 请求,但是,从后端获取一些数据的初始提取工作......

【问题讨论】:

【参考方案1】:

您必须将服务器端和客户端请求分开。您需要将主机地址用于客户端请求(例如http://localhost:7766),因为您的浏览器将无法通过 docker 别名访问后端。

您可以使用next.config.js 定义仅服务器和公共运行时配置。

例如:

// next.config.js
module.exports = 
  serverRuntimeConfig: 
    // Will only be available on the server side
    apiUrl: 'http://dcbackend:7766'
  ,
  publicRuntimeConfig: 
    // Will be available on both server and client
    apiUrl: 'http://localhost:7766'
  

然后你需要从 nextjs 获取apiUrlgetConfig()

// pages/index.js
import getConfig from 'next/config';

const  serverRuntimeConfig, publicRuntimeConfig  = getConfig();

const apiUrl = serverRuntimeConfig.apiUrl || publicRuntimeConfig.apiUrl;

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

Index.getInitialProps = async () => 
    try 
       const res = await fetch(`$apiUrl/doubletten/304699981`);
       const json = await res.json();
       return  json ;
     catch(e) 
       console.log('Failed to fetch', e);
       return  json: null ;
    


export default Index;

【讨论】:

首先,谢谢。这对解决我已经尝试解决了几个小时的问题有很大帮助。其次,你有没有文章或者你能解释为什么会发生这种情况,我想我理解了你的解释,但我觉得我仍然错过了一些东西。最后,像 k8s 这样的服务也会发生这种情况吗?再次感谢您的所有回答。 *** 上有点新,所以不知道在这里问这类问题是否合适。提前致谢,祝您有美好的一天! 我试过按照你的方式做,但我的 serverRuntimeConfig 总是空对象

以上是关于Docker-compose 使 2 个微服务(前端+后端)通过 http 请求相互通信的主要内容,如果未能解决你的问题,请参考以下文章

Linux企业运维——Docker三剑客之docker-compose

11:docker-compose(单机版的容器编排工具)

关于docker那点事儿——docker compose简介

使用docker-compose时,Healthcheck根本不起作用(我的服务在启动前不等待Kafka启动)

配置 Prometheus 监控多个微服务

springCloud分布式事务实战编写第二个微服务