【问题标题】:Use Eureka despite having random external port of docker containers尽管有 docker 容器的随机外部端口,但仍使用 Eureka
【发布时间】:2015-07-10 09:39:04
【问题描述】:

我正在编写一个应用程序,它由几个基于 Spring Boot 的微服务组成,前端有一个基于 zuul 的反向代理-

当我在我的机器上启动服务时它可以工作,但对于服务器部署,我想使用 docker 来提供服务,但这似乎现在不可能。

通常情况下,您会在容器外部有一个固定的“内部”端口和随机端口。但容器中的应用不知道外部端口(和 IP)。

Netflix 工具与我想要编写一个高效的微服务架构相匹配,并且在概念上我真的很喜欢 docker。 据我所知,启动容器会很麻烦,在主机上收集外部端口并传递给应用程序,因为您不能在应用程序启动后简单地更改端口。

有什么方法可以将 eureka 与基于 docker 的客户端一起使用?

[更新] 我想我在解释问题方面做得很差。所以也许这更能澄清一点:

eureka 服务器本身可以在 docker 中运行,因为我只有一个,外部端口无所谓。我可以使用链接功能从客户端访问它。

问题在于客户端注册自己的 URL。 例如 https://localhost:8080/ 但由于动态端口分配,它实际上只能通过 https://localhost:54321/ 访问

所以 eureka 会返回错误的服务 URL。

更新 我已经在下面更新了我的答案,所以看看那里。

【问题讨论】:

  • 你在registry.hub.docker.com/search?q=eureka&searchfield= 和 3 zuul registry.hub.docker.com/search?q=zuul&searchfield= 上有 14 个带有 Eureka 的 docker 镜像,也许你应该看看相关的 Dockerfiles
  • 问题是没有带有 eureka 的 docker 镜像。问题是客户端无法使用随机外部端口在 eureka 中注册,因为应用程序本身只知道内部端口。
  • >>> app 本身只知道内部端口 --> 可以使用卷来读写内部端口,见docs.docker.com/userguide/dockervolumesdocker run --volumes-from
  • 嗯,有办法获取主机上的外部端口,那么还有任务让eureka客户端使用这个而不是检测到的内部端口。我希望有人已经尝试过使用这种组合。
  • 你是在一台机器上运行更多的 docker 实例(同一个服务),还是为什么你不能有固定的(外部)端口?

标签: docker spring-boot netflix-eureka netflix-zuul


【解决方案1】:

我自己找到了一个解决方案,这可能不是最好的解决方案,但它适合我......

当您使用“--net=host”(主机网络)启动 docker 时,您可以直接使用主机网络堆栈。然后我只是使用 0 作为 spring-boot 的端口,spring 为我随机化了端口,因为它使用主机网络堆栈,所以没有转换到不同的端口(和 IP)。

但也有一些缺点:

  • 当您使用主机网络时,您不能将这些容器的链接功能用作链接源或目标。
  • 使用 hosts 网络堆栈会导致对实例的封装较少,这可能是您的项目的问题。

希望对你有帮助

已经过了很多时间,我想我应该再详细说明一下:

  1. 如果您使用 docker 托管您的 spring 应用程序,请不要使用随机端口!使用固定端口,因为每个容器都有自己的 IP,因此每个服务都可以使用相同的端口。这让生活更轻松。

  2. 如果您有面向公众的服务,那么无论如何您都会使用固定端口。

  3. 对于通过 maven 或例如命令行的本地启动,有一个使用随机端口的专用配置文件,因此您不会发生冲突(但请注意,随机端口和服务周围存在或曾经存在一些错误注册)

  4. 如果出于某种原因您想要或需要使用主机网络,您当然可以使用随机端口,但大多数时候您不应该这样做!

【讨论】:

  • 在 AWS 中,每个服务都在它自己的主机上,对吧?那么你可以使用“常规”(又名 Netflix)方式并使用固定端口,对吗?
  • 端口没有问题,主机有问题。在容器内部,我无法确定主机的 IP 地址。但是 AWS SDK 能够做到这一点,我以编程方式解决了我的问题。
【解决方案2】:

您可以为每个 docker 实例设置一个目录,并在主机和实例之间共享它,然后将端口和 IP 地址写入该目录中的文件。

$ instanceName=$(generate random instance name)
$ dirName=/var/lib/docker/metadata/$instanceName
$ mkdir -p $dirName
$ docker run -name $instanceName -v ${dirName}:/mnt/metadata ...
$ echo $(get port number and host IP) > ${dirName}/external-address

然后您只需从应用程序中读取 /mnt/metadata/external-address 并将该信息与 Eureka 一起使用。

【讨论】:

  • 感谢您的方法!我想过类似的事情。这需要有一个特殊的启动脚本来等待在启动应用程序之前设置端口和 IP 数据。由于我计划稍后使用 Kubernetes 之类的东西进行扩展和管理,因此我希望尽可能降低对特殊脚本的需求。
  • 您可以在您的应用程序中轮询文件并在填充后向 Eureka 注册。虽然在启动容器时确实需要特殊处理。
  • 正确,只要主机网络模式没问题我就用那个。当我必须使用标准网络时,我会尝试您的建议。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-30
  • 1970-01-01
相关资源
最近更新 更多