微服務加速和簡化構建Docker(基於Google jib)

準備

  • Maven3.5
  • Git
  • Jdk 1.8
  • Docker
$ git clone https://github.com/anjia0532/jib-demo.git
$ cd jib-demo
$ mvn clean package -DskipTests
$ mkdir docker
$ cp ./target/*.jar ./docker

Dockerfile

創建 ./docker/Dockerfile ,內容如下,需要注意此處為了方便理解,沒有進行改進(比如限制用戶,安裝必要軟件等)

FROM openjdk:8-jdk-alpine
ADD *.jar /app.jar
EXPOSE 8080
CMD java ${JAVA_OPTS} /app.jar

詳情參見 官方文檔 Dockerfile reference

$ cd ./docker
$ sudo docker build . -t jib-demo
$ docker images --查看本地images
$ docker tag jib-demo anjia0532/jib-demo --不寫registry,則默認為docker hub registry,可以在build時,直接寫
$ docker push anjia0532/jib-demo -- 推送到registry

小結

優點: 不需要改造pom,靈活,配合CI工具,可以不侵入項目,運維可以針對性的進行安全加固,並且可以做到標準化

缺點: 命令複雜,Java程序員需要學習Dockerfile命令,或者運維和java溝通不暢時,時區,軟件,甚至目錄等都可能有出問題

spotify/dockerfile-maven

需要注意,spotify/dockerfile-maven 是需要pom+Dockerfile一塊用的,而docker-maven-plugin是可選的

在項目根目錄創建Dockerfile,如下所示

FROM openjdk:8-jdk-alpine
EXPOSE 8080
ARG JAR_FILE
ADD target/${JAR_FILE} /usr/share/myservice/myservice.jar
ENTRYPOINT ["/usr/bin/java", "-jar", "/usr/share/myservice/myservice.jar"]

在pom裡增加dockerfile-maven-plugin到build標籤裡

<build>
<plugins>
...
<plugin>
<groupid>com.spotify/<groupid>
<artifactid>dockerfile-maven-plugin/<artifactid>
<version>${dockerfile-maven-version}/<version>
<executions>
<execution>
default
<goals>
<goal>build/<goal>
<goal>push/<goal>
/<goals>
/<execution>
/<executions>
<configuration>
<repository>anjia0532/dockerfile-maven-demo/<repository>
${project.version}

<buildargs>
${project.build.finalName}.jar
/<buildargs>
/<configuration>
/<plugin>
...
<plugins>
<build>
/<build>/<plugins>/<plugins>/<build>

運行如下命令進行構建

$ mvn package -DskipTests

詳情參見 官方文檔 spotify/dockerfile-maven

小結

優點: 減少了docker build & tag & push 的操作,Java程序員能夠控制鏡像名

**缺點: **其實就是省了docker build & tag & push的操作,別的缺點一點沒落不說,還得改動pom,還得要求寫Dockerfile,tag只支持一個等等

Google jib

修改默認settings.xml,增加registry認證,參見Authentication Methods

<settings>
...
<servers>
...
<server>
docker_hub
<username>MY_USERNAME/<username>

<password>{MY_SECRET}/<password>
/<server>
/<servers>
/<settings>

改動pom.xml 增加 jib插件

<project>
...
<build>
<plugins>
...
<plugin>
<groupid>com.google.cloud.tools/<groupid>
<artifactid>jib-maven-plugin/<artifactid>
<version>1.0.0/<version>
<configuration>
<from>

<image>registry.hub.docker.com/hengyunabc/arthas:latest/<image>
<credhelper>docker_hub/<credhelper>
/<from>

<image>${project.artifactId}/<image>
<tags>
latest
${project.version}
/<tags>

<container>
<mainclass>${start-class}/<mainclass>
<ports>
<port>8080/<port>
<port>5701/udp/<port>
<port>8563/<port>
/<ports>
<entrypoint>
<shell>sh/<shell>
<option>-c/<option>
java -cp /app/resources/:/app/classes/:/app/libs/* com.example.demo.DemoApplication

/<entrypoint>
<approot>/app/<approot>
<usecurrenttimestamp>true/<usecurrenttimestamp>
/<container>
/<configuration>
/<plugin>
...
/<plugins>
/<build>
...
/<project>

執行mvn clean compile jib:dockerBuild 構建docker鏡像

注意:

pom中用的是 registry.hub.docker.com/hengyunabc/arthas:latest 是 alibaba/arthas (阿里開源的一個Java診斷工具,便於線上調試)封裝的docker鏡像,如果不需要可以改成 registry.hub.docker.com/openjdk:8-jdk-alpine

$ docker run -d --init -p8563:8563 --name demo demo:latest
## 下面是啟動arthas,如果使用的是openjdk鏡像請勿執行
$ docker exec -it demo /bin/sh
$ jid=$(jps | grep App | awk '{print $1}')
$ java -jar /opt/arthas/arthas-boot.jar --target-ip 0.0.0.0 ${jid}

如果使用了arthas鏡像,可以訪問 http://ip:8563 ,在頁面上填上宿主ip,點擊Connect, 然後參考Arthas/命令列表 瞭解Arthas命令用法

微服務加速和簡化構建Docker(基於Google jib)

小結

優點: 充分利用緩存,加快構建,不強制依賴docker daemon,依賴簡單(在maven或gradle增加插件即可)

缺點: 不支持Docker RUN 命令(jib官方建議將run封裝到base鏡像),對entrypoint和cmd支持不太好(alpine默認不支持多任務,跑java應用默認是pid 1 ,運行jmap等命令會報錯,參考 jmap not happy on alpine )

jib 緩存策略

項目每次發佈實際上變更的代碼量不大,尤其依賴的jar變動的可能性較小,如果按照前兩種方案構建鏡像,會導致每次都全量構建,會導致存儲和帶寬資源浪費。

Jib 如何讓開發變得更美好

Jib 利用了 Docker 鏡像的分層機制,將其與構建系統集成,並通過以下方式優化 Java 容器鏡像的構建:

  • 簡單——Jib 使用 Java 開發,並作為 Maven 或 Gradle 的一部分運行。你不需要編寫 Dockerfile 或運行 Docker 守護進程,甚至無需創建包含所有依賴的大 JAR 包。因為 Jib 與 Java 構建過程緊密集成,所以它可以訪問到打包應用程序所需的所有信息。在後續的容器構建期間,它將自動選擇 Java 構建過的任何變體。
  1. 快速——Jib 利用鏡像分層和註冊表緩存來實現快速、增量的構建。它讀取你的構建配置,將你的應用程序組織到不同的層(依賴項、資源、類)中,並只重新構建和推送發生變更的層。在項目進行快速迭代時,Jib 只講發生變更的層(而不是整個應用程序)推送到註冊表來節省寶貴的構建時間。
  2. 可重現——Jib 支持根據 Maven 和 Gradle 的構建元數據進行聲明式的容器鏡像構建,因此,只要輸入保持不變,就可以通過配置重複創建相同的鏡像。

可以可以通過 mvn clean compile jib:buildTar 生成 target/jib-image.tar 然後用解壓縮工具解壓後進行分析,實際上jib會將lib中非快照部分放到一個層,將快照部分放到一個層,將源碼編譯後放到一個層。。。

微服務加速和簡化構建Docker(基於Google jib)

關注我:私信回覆“555”獲取往期Java高級架構資料、源碼、筆記、視頻Dubbo、Redis、Netty、zookeeper、Spring cloud、分佈式、高併發等架構技術往期架構視頻截圖


分享到:


相關文章: