我们将微服务应用程序停靠,我遇到了一些发现问题。
该应用程序配置如下:
当服务以“非本地”模式启动时,它使用Consul作为其Discovery注册表。 当服务以“本地”模式启动时,它会自动绑定每个服务的地址(例如,tcp:// localhost:61001,tcp:// localhost:61002等等。硬编码地址)
将应用程序停靠后(仅适用于本地模式),每个服务都是一个容器(使用docker-compose编写的Docker镜像。如果重要的话,使用docker-machine) 但是一个服务不能与另一个服务交互,因为它们不在同一台机器上,tcp:// localhost:61001显然不起作用。
将docker-compose与links一起使用并将localhost指定为别名(service:localhost)不起作用。 2个容器是否有办法“共享”同一个本地主机?
如果没有,最好的方法是什么? 我考虑过为每个服务使用特定的主机名,然后在docker-compose的links部分指定主机名。 (但我怀疑这是优雅的解决方案) 或者可以使用Consul的版本化版本并与之集成?
这篇文章:How to share localhost between two different Docker containers?提供了一些关于为什么不应该将localhost搞砸的见解 - 但我仍然对这里的正确方法感到困惑。
谢谢!
答案 0 :(得分:6)
但是一个服务无法与另一个服务交互,因为它们不在同一台机器上,而tcp:// localhost:61001显然不起作用。
实际上,他们可以。你是对的tcp://localhost:61001
不起作用,因为在容器中使用localhost
将引用容器本身,类似于默认情况下localhost
在任何系统上的工作方式。这意味着您的服务无法共享同一主机。如果你想要它们,你可以为这两种服务使用一个容器,虽然这真的不是最好的设计,因为它击败了Docker Compose的主要目的之一。
理想的方法是使用docker-compose链接,您引用的指南显示了如何定义它们,但实际上使用它们需要在URL中使用链接容器的名称,就好像链接容器的名称在原始容器的/etc/hosts
中定义了一个IP映射(实际上并不是这样,但只是让你明白了)。如果要将其更改为与链接容器名称不同的内容,可以使用链接别名,这在您引用的同一指南中有说明。
例如,使用docker-compose.yml
这样的文件:
a:
expose:
- "9999"
b:
links:
- a
a
0.0.0.0:9999
b
通过a
向b
提出请求,tcp://a:9999
可以与b
进行互动。也可以归入ping a
并运行
a
会从b
容器向localhost
容器发送ping请求。
因此,最后,尝试使用链接容器的文字名称替换请求URL中的tcp://<container_name>:61001
(如果使用别名定义链接,则使用链接别名)。这意味着
tcp://localhost:61001
应该起作用而不是
docker-compose.yml
只需确保在/usr/bin/python
中定义链接。
希望这有帮助
答案 1 :(得分:3)
在制作时,不要单独使用docker或docker。使用一个orchestrator(牧场主,docker swarm,k8s,...)并在那里部署你的堆栈。 Orchestrator将负责网络问题。您的容器可以相互链接,因此您可以通过名称直接访问它们(不要太在意ip)。
在本地主机上,使用docker compose启动容器并使用链接。不要使用本地端口,而是使用链接的名称。 (如果您的容器A需要访问端口1234上的容器B,则执行链接B链接到名称为BBBB的A并使用tcp:// BBBB:1234从A访问容器
如果你真的想将端口绑定到localhost并使用它,请通过主机IP访问端口,而不是localhost。
答案 2 :(得分:2)
如果现在不能更改硬编码地址,也许您可以修改容器的启动脚本,将每个本地容器中的前端转发到其他机器中的所需服务。
这会产生一些复杂性,因为您必须在每个容器中设置ssh,并管理相应的密钥。
想想看,如果加密不是问题,则不需要ssh。使用socat或redir会probably be enough。
socat TCP4-LISTEN:61001,fork TCP4:othercontainer:61001