Docker的組合優於繼承 - frankel

banq發表於2019-11-19

Docker和容器化技術僅存在了一段時間。要了解如何充分利用自己的情況,可能需要花費一些時間以及一些反覆試驗。這篇文章介紹了許多可用選項之一。

Docker容器的主要優點是它們是獨立的。對於開發人員來說,這意味著只需要從包含所需必需依賴項的所需Docker映象繼承即可,並且可以構建自己的應用程式將其交付生產。在大多數情況下,該過程非常簡單。容器化允許前所未有的規模擴充套件。

但是,這種自包含的缺點是更新父映象會成為噩夢。該過程如下:

  1. 使用新的父映象更新Dockerfile
  2. 生成新映象
  3. 生成的映象可在Docker登錄檔中使用
  4. 最後,將其從生產計算機上的登錄檔中提取出來,然後啟動

雖然偶爾為單個映像接受可能會出現這種情況,但是隨著更新頻率的增加以及涉及的容器化應用程式數量的增加,這絕對是不可行的。

現在,讓我們考慮一下自包含性與靈活性之間的權衡,並放寬約束。與其從映象繼承,不如公開包含所需依賴項的資料夾:與繼承完全相同,這是偏愛組成的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正在成為事實上的部署平臺。

 

相關文章