Docker和容器化技术仅存在了一段时间。要了解如何充分利用自己的情况,可能需要花费一些时间以及一些反复试验。这篇文章介绍了许多可用选项之一。
Docker容器的主要优点是它们是独立的。对于开发人员来说,这意味着只需要从包含所需必需依赖项的所需Docker镜像继承即可,并且可以构建自己的应用程序将其交付生产。在大多数情况下,该过程非常简单。容器化允许前所未有的规模扩展。
但是,这种自包含的缺点是更新父镜像会成为噩梦。该过程如下:
虽然偶尔为单个映像接受可能会出现这种情况,但是随着更新频率的增加以及涉及的容器化应用程序数量的增加,这绝对是不可行的。
现在,让我们考虑一下自包含性与灵活性之间的权衡,并放宽约束。与其从镜像继承,不如公开包含所需依赖项的文件夹:与 继承 完全相同,这是 偏爱组成的 OOP原理!通过这种设计,只需替换合成的镜像即可更新所需的二进制文件。
作为示例,我将创建一个包含此设计的简单Java应用程序。我假设一个生成可执行JAR的Maven项目。这是相关的Dockerfile:
Docker文件
FROM maven:3.6.0-alpine as build COPY src src COPY pom.xml . RUN mvn package FROM alpine:3.8 COPY --from=build target/composition-example-1.0-SNAPSHOT.jar . ENTRYPOINT ["sh", "-c", "/usr/bin/java -jar composition-example-1.0-SNAPSHOT.jar"]
这是一个多阶段构建,首先构建Maven项目,然后运行/usr/bin/java。
请注意,标准Dockerfiles将继承自基本JRE镜像,例如openjdk:8-jre-alpine。在这里,第二阶段从基础alpine镜像继承,因为没有发现可执行文件java,因此,运行构建的Docker镜像将失败:
$ docker build -t compose-this . $ docker run compose-this -jar: line 1: java: not found
为了解决这个问题,让我们创建一个在镜像中公开其java可执行文件的Docker镜像:
FROM openjdk:8-jre-alpine VOLUME /usr/bin VOLUME /usr/lib
虽然java位于/usr/bin,它只是指向一个符号链接/usr/lib/jvm/default-jvm/jre/bin/java。因此,该/usr/lib文件夹也需要公开。
生成并运行该映像:
docker build -t myjava:8 . docker run --name java myjava:8
此时,可以将java容器中的卷绑定到运行该compose-this镜像的新容器:
docker run -it --volumes-from java compose-this
现在不仅可以更轻松地更新从属JRE,而且还有一个好处是,与独立镜像相比,应用程序镜像已大大减少:它仅包含JAR。
可能会出现一个问题:在文件系统上使用纯JAR和共享JRE的情况下,此设置与未容器化的设置之间会有什么区别?
允许编排,即 Kubernetes。虽然可以使用配置管理工具(例如 Puppet或Chef)来实现相同的目的,但Kubernetes正在成为事实上的部署平台。