从在主机B上运行的Docker连接到主机A

时间:2018-11-04 19:38:45

标签: docker docker-compose

我开发分布式系统,并考虑以下情况: 我的应用程序正在主机A上运行的docker中工作,我想从物理主机B上运行的其他服务(无docker)调用api。我可以调用IP或DNS地址吗?

与上述问题有关的其他情况: 我使用docker-compose在本地开发分布式系统,并在其中定义了服务:ServiceA,ServiceB等。如果ServiceA必须在端口8080上调用ServiceB,请致电http://ServiceB:8080/,它可以正常工作。在生产中,每个服务应在具有不同IP的不同主机上工作。那么,我将在不同的主机上运行每个服务,并通过http://<IP_of_ServiceB>:8080而不是使用服务名从ServiceA调用到ServiceB的好方法吗?

2 个答案:

答案 0 :(得分:2)

第一个问题,是的,只需确保端口已暴露且可从其他主机访问。

第二个问题,您仍然可以这样做(在环境中记下主机B的IP)。或者,您可能要考虑使用docker swarm部署生产堆栈。结合覆盖网络,使您的2个主机像一个主机一样,您可以像http://ServiceB:3000/

那样继续通话
version: '3'
services:
  serviceA:
    image: serviceA
    ports:
      - "8080:8080"
    networks: 
      - swarm-net

  serviceB:
    image: serviceB
    networks: 
      - swarm-net
    ports:
      - "3000:3000"

networks:
  swarm-net:
    driver: overlay

答案 1 :(得分:2)

您可能会发现有用的一个基础架构部分是服务注册表,该注册表知道哪些主机正在运行哪些服务。它们通常提供DNS服务,因此您可以通过服务的“主机名”引用服务,并将其路由到运行该服务的实际主机。这里的想法是通过(可能是人为的)主机名引用Docker服务和非Docker服务,并且基础结构层将其路由到正确的主机。除了Kubernetes选项外,除了指向正确的DNS服务器之外,这些不需要特殊的网络设置。

我之前使用过三个具体示例:

  • 在AWS上(如果您已经在使用/付款),则可以通过运行状况检查在每个节点上设置一个load balancer;如果某个节点碰巧正在服务(例如)端口9123,则负载均衡器的端口80将路由到该端口。然后,您可以设置指向负载均衡器的DNS name。对于每种服务,请在您关心的节点上的特定已知端口上启动它,并为每个服务创建负载平衡器和DNS名称。 (您也可以创建DNS CNAME记录,这些记录是外部服务主机的别名。)这恰好是ECS的标准设置,但并不专门与该服务相关;实际上,如果您可以提供自己的负载平衡器和名称服务器,则可以在任何地方使用此方法。

  • Hashicorp的Consul旨在(除其他外)用作服务注册中心。在我过去使用的模式下,您将在每个节点上安装Consul代理,然后在每个节点上安装一组运行状况检查,以查找每个已知服务。配置您的Docker容器以指向Consul DNS服务器。诸如servicename.service.consul之类的主机名将解析为运行该服务的主机的IP地址,然后您可以使用该服务的端口引用诸如http://servicename.service.consul:9123/之类的URL。 (我相信您可以在服务的definition中覆盖服务的地址,以将其指向外部服务器。)

  • Kubernetes中,有一个标准Service对象提供负载平衡和DNS。您可以将服务配置为在某些端口上侦听并路由到某些Pod集(依次运行Docker容器)上的其他端口。您将使用主机名,例如servicename.default.svc.cluster.local,但是大多数主机名也会出现在默认的DNS搜索路径中,因此,http://servicename/通常是一个很好的URL。 (您可以配置ExternalName服务,该服务只是指向群集外部的DNS记录。)