使用Maven加速和簡化構建Docker(基於Google jib)

介紹

其實jib剛發佈時就有關注,可是一直沒有用於生產,緣由有二php

先簡單介紹一下: google jib 是Google於18年7月發佈的一個針對Java應用的構建鏡像的工具(支持MavenGradle) ,好處是可以複用構建緩存,可以加快構建,減少傳輸體積(後文會詳細講解),而且讓Java工程師不須要理解Docker相關知識就能夠簡單構建鏡像而且發佈到指定registry裏(不須要docker build , tag, push)html

本文會依次講解三種java構建鏡像的方法,分別是 正統的Dockerfile ,spotify/dockerfile-maven ,Google jib 
附贈 alibaba/arthas 的集成和使用方法java

google jib 和 Dragonfly 系列文章git

準備

  • 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 referencegithub

$ 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溝通不順暢時,時區,軟件,甚至目錄等均可能有出問題docker

spotify/dockerfile-maven

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

在項目根目錄建立Dockerfile,以下所示segmentfault

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命令用法

snipaste20190208_201332.png

小結

優勢: 充分利用緩存,加快構建,不強制依賴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 容器鏡像的構建:

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

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

snipaste20190208_211839.png

參考資料

招聘小廣告

山東濟南的小夥伴歡迎投簡歷啊 加入咱們 , 一塊兒搞事情。

長期招聘,Java程序員,大數據工程師,運維工程師。

相關文章
相關標籤/搜索