加速和簡化構建Docker(基於Google jib)
介紹
其實jib剛釋出時就有關注,但是一直沒有用於生產,原因有二
- 基於 spotify/docker-maven-plugin (原作者已經停止維護docker-maven-plugin,建議使用 spotify/dockerfile-maven)的原有流程跑的好好的,沒動力換成jib
- Google jib 一直沒有釋出1.x ,擔心其不穩定
先簡單介紹一下: google jib 是Google於18年7月釋出的一個針對Java應用的構建映象的工具(支援Maven和Gradle) ,好處是能夠複用構建快取,能夠加快構建,減小傳輸體積(後文會詳細講解),並且讓Java工程師不需要理解Docker相關知識就可以簡單構建映象並且釋出到指定registry裡(不需要docker build , tag, push)
本文會依次講解三種java構建映象的方法,分別是 正統的Dockerfile ,spotify/dockerfile-maven ,Google jib
附贈 alibaba/arthas 的整合和使用方法
準備
- 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>
<id>default</id>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions>
<configuration>
<repository>anjia0532/dockerfile-maven-demo</repository>
<tag>${project.version}</tag>
<buildArgs>
<JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
...
<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>
<id>docker_hub</id>
<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>
<!-- 如果不需要arthas可以改為 registry.hub.docker.com/openjdk:8-jdk-alpine -->
<image>registry.hub.docker.com/hengyunabc/arthas:latest</image>
<credHelper>docker_hub</credHelper>
</from>
<to>
<image>${project.artifactId}</image>
<tags>
<tag>latest</tag>
<tag>${project.version}</tag>
</tags>
</to>
<container>
<mainClass>${start-class}</mainClass>
<ports>
<port>8080</port>
<port>5701/udp</port>
<port>8563</port>
</ports>
<entrypoint>
<shell>sh</shell>
<option>-c</option>
<arg>java -cp /app/resources/:/app/classes/:/app/libs/* com.example.demo.DemoApplication</arg>
</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 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 構建過的任何變體。
- 快速——Jib 利用映象分層和登錄檔快取來實現快速、增量的構建。它讀取你的構建配置,將你的應用程式組織到不同的層(依賴項、資源、類)中,並只重新構建和推送發生變更的層。在專案進行快速迭代時,Jib 只講發生變更的層(而不是整個應用程式)推送到登錄檔來節省寶貴的構建時間。
- 可重現——Jib 支援根據 Maven 和 Gradle 的構建後設資料進行宣告式的容器映象構建,因此,只要輸入保持不變,就可以通過配置重複建立相同的映象。
可以可以通過 mvn clean compile jib:buildTar
生成 target/jib-image.tar
然後用解壓縮工具解壓後進行分析,實際上jib會將lib中非快照部分放到一個層,將快照部分放到一個層,將原始碼編譯後放到一個層。。。
參考資料
招聘小廣告
山東濟南的小夥伴歡迎投簡歷啊 加入我們 , 一起搞事情。
長期招聘,Java程式設計師,大資料工程師,運維工程師。