一、背景
Docker鏡像采用了分層結構,如果所有的應用程序都使用了相同的基礎鏡像,就可以節省 Docker 注冊表的存儲空間,上傳和下載鏡像的速度也更快了,因為只需要傳輸更少的文件量(Docker 只會將新的層傳輸到注冊表中)。一般公司由於網絡條件限制,導致應用發布時傳輸速度較慢,因此需要考慮優化Docker鏡像構建。
以下是系統中典型的鏡像分層結構(通過docker history查看),其中每一行代表一個鏡像層,上半部分紅色框內的是應用程序構建的鏡像層,下半部分是源鏡像層。源鏡像層很少改動,每次構建都會復用,本文中所作的優化是針對上半部分的應用程序鏡像層。
二、優化方案
采用JIB工具對Spring Boot應用程序進一步分層,將其中的依賴項、資源文件和應用代碼構建為獨立的鏡像層,由於依賴項通常體積較大且改動較少,因此能充分利用鏡像分層復用的機制。
三、實施步驟
1.修改項目的父POM
- 在
<properties>
中加入以下自定義property:
<image.tag>default</image.tag>
<registry.username>default</registry.username>
<registry.password>default</registry.password>
- 在
<pluginManagement>
中加入JIB插件及相關配置,此處配置包含了Dockerfile中的內容(Dockerfile不再起作用,建議刪除)
- 為方便起見,將鏡像構建過程綁定到Maven的install生命周期中;
- configuration.from.image中配置源鏡像地址,configuration.to.image中配置目標鏡像推送地址,下圖中的xxxx對應於鏡像倉庫中各項目的namespace;
- container.creationTime須配置符合DateTimeFormatter.ISO_DATE_TIME格式的時間,例如2019-07-15T10:15:30+08:00。如果設置為當前時間(USE_CURRENT_TIMESTAMP),則每次生成的鏡像就不相同,從而無法復用,因此,僅當依賴項改動時再去更新該時間。
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>1.8.0</version>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<allowInsecureRegistries>true</allowInsecureRegistries>
<from>
<image>registry.cn-hangzhou.aliyuncs.com/kancy/openjdk:8-jre-alpine</image>
<auth>
<username>${registry.username}</username>
<password>${registry.password}</password>
</auth>
</from>
<to>
<image>registry.cn-hangzhou.aliyuncs.com/kancy/${project.artifactId}-jib</image>
<auth>
<username>${registry.username}</username>
<password>${registry.password}</password>
</auth>
<tags>
<tag>${latest}</tag>
<tag>${image.tag}</tag>
</tags>
</to>
<container>
<!-- <creationTime>2020-05-01T10:00:00+08:00</creationTime>-->
<creationTime>USE_CURRENT_TIMESTAMP</creationTime>
<volumes>/tmp</volumes>
<workingDirectory>/home</workingDirectory>
<environment>
<TZ>Asia/Shanghai</TZ>
</environment>
</container>
</configuration>
</plugin>
注意:
以上配置項僅包含了目前一般Springboot項目中典型的Dockerfile內容(如下所示),如果在原Dockerfile中有額外命令,需要在POM文件中添加相應的配置,或考慮包含到源鏡像中,詳情可參考官方文檔。
3)docker registry 認證信息也可以配置在settings.xml
其中server.id為 docker registry倉庫地址
<servers>
<server>
<id>registry.cn-hangzhou.aliyuncs.com</id>
<username>kancy1994</username>
<password>********</password>
</server>
</servers>
2. 修改各應用的POM文件
在build.plugins內加入以下項即可,注意非應用類型的module不要添加。
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
</plugin>
3. 在Rancher管理界面中修改應用配置中的環境變量名稱
更新以下環境變量名稱:
JAVA_OPS替換為: JAVA_TOOL_OPTIONS
PROFILE 替換為: spring.profiles.active
或者
JAVA_TOOL_OPTIONS = "-Xmx1024m -Dspring.profiles.active=sit"
注:原Dockerfile啟動命令中如果定義了其他環境變量,也需要在此添加。
四、查看效果
以下是JIB構建的鏡像,可以看到應用程序中的依賴項、資源文件和應用代碼被構建為獨立的鏡像層。應用重新構建時如果沒有改動依賴項,則只有極少的文件量需要傳輸。
五、注意事項
如果你的docker registry倉庫不支持https,那么maven打包的時候需要指定使用http模式,默認是https模式。
mvn clean package -DsendCredentialsOverHttp=true