一、背景
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