每个 Docker 镜像都应该包含一个 JDK 吗?这种方法是否正确?是否应该将 DockerHub 中的“OpenJDK”添加到每个映像中?为什么即使目标 PC 可能已经具有 JDK,映像的大小也会很大?(暗示)每个应用/微服务都应该在自己的容器中吗?

2022-09-01 15:44:36

所以,我对Docker很陌生。让我解释一下这个问题的背景。

  1. 我有 10 - 20 个 Spring Boot 微服务应用程序,每个应用程序都在本地计算机上的不同端口上运行。

  2. 但是,为了迁移到 Docker,根据我的学习,每个服务都必须位于不同的 Docker 容器中,以便快速部署或复制。

  3. 对于每个 Docker 容器,我们需要创建一个新的 Docker 映像。

  4. 每个 Docker 映像必须包含一个 JRE,才能运行 Spring Boot 应用程序。最大值约为 200 MB。这意味着每个 Docker 映像最大为 350 MB。另一方面,在我的本地PC上,我只有一个200 MB的JRE,每个应用程序只占用几MB的空间。

  5. 基于此,我在本地系统上需要 600 MB,但所有 Docker 映像都需要 7 GB。

这种方法是否正确?是否应该将 DockerHub 中的“OpenJDK”添加到每个映像中?

为什么即使目标 PC 可能已经具有 JDK,映像的大小也会很大?


答案 1

你的理解是不正确的。

Docker镜像是用层形成的;见下图:

当您在映像中安装 JRE 时,假设它的校验和在下一张图片中,它将真正占用您的磁盘。91e54dfb1179

但是,如果你所有的容器都基于相同的映像,并且添加不同的东西,比如说,你的不同微服务应用程序到瘦R/W层,那么所有容器都将共享,所以它不会是n*m关系。91e54dfb1179

您需要注意尽可能对所有 Java 应用程序使用相同的基本映像,并在精简的 R/W 层中添加不同的东西。

Enter image description here


答案 2

其他答案很好地涵盖了Docker分层,所以我只想为你的问题添加细节

这种方法是否正确?是否应该将 DockerHub 中的“OpenJDK”添加到每个映像中?

是的。如果它不在映像中,则不会在容器中。但是,您可以通过重复使用尽可能多的图层来节省磁盘空间。因此,请尝试将 Dockerfile 从“最不可能更改”编写为“最有可能更改”。因此,当您构建映像时,看到“使用缓存”的频率越高越好。

为什么即使目标 PC 可能已经具有 JDK,映像的大小也会很大?

Docker 希望尽可能少地与主机相关。Docker甚至不想与主机打交道。它做的第一件事是创建一个要隐藏的 VM。Docker 映像假设主机唯一能提供的就是空 RAM、磁盘和 CPU。因此,每个 Docker 映像还必须包含它自己的操作系统/内核。(这就是你最初的 FROM 正在做的事情,选择一个基本的操作系统映像来使用)因此,您的最终图像大小实际上是操作系统+工具+应用程序。图像大小有点误导,因为它是所有图层的总和,这些图层在图像中重复使用。

(暗示)每个应用/微服务都应该在自己的容器中吗?

理想情况下,是的。通过将应用转换为隔离模块,可以更轻松地替换/负载均衡该模块。

在实践中,也许不是(对你来说)。Spring Boot不是一个轻量级的框架。实际上,它是一个用于模块化代码的框架(在模块控制系统内有效运行模块控制系统)。现在你想托管其中的10-20个吗?这可能无法在单个服务器上运行。Docker将强制Spring boot将自身加载到每个应用程序的内存中;并且对象现在不能跨模块重用,因此这些对象也需要进行多重实例化!如果您被限制为 1 台生产服务器,则无法进行水平扩展。(每个Spring Boot需要大约1GB的HEAP(RAM),根据您的代码库来节省我的里程)。对于 10-20 个应用,重构以使应用更轻量级以进行 Docker 部署可能不可行/预算不合理。更不用说,如果您无法在本地运行最小的设置进行测试(RAM不足),则开发工作将变得更加“有趣”。

Docker不是一把金锤子。试一试,自己评估利弊,并决定利弊是否值得您和您的团队。


推荐