Docker镜像分层打包方案

一、背景

Docker镜像采用了分层结构,如果所有的应用程序都使用了相同的基础镜像,就可以节省 Docker 注册表的存储空间,上传和下载镜像的速度也更快了,因为只需要传输更少的文件量(Docker 只会将新的层传输到注册表中)。一般公司由于网络条件限制,导致应用发布时传输速度较慢,因此需要考虑优化Docker镜像构建。

以下是系统中典型的镜像分层结构(通过docker history查看),其中每一行代表一个镜像层,上半部分红色框内的是应用程序构建的镜像层,下半部分是源镜像层。源镜像层很少改动,每次构建都会复用,本文中所作的优化是针对上半部分的应用程序镜像层。

二、优化方案

采用JIB工具对Spring Boot应用程序进一步分层,将其中的依赖项、资源文件和应用代码构建为独立的镜像层,由于依赖项通常体积较大且改动较少,因此能充分利用镜像分层复用的机制。

三、实施步骤

1.修改项目的父POM

  1. <properties>中加入以下自定义property:
<image.tag>default</image.tag>
<registry.username>default</registry.username>
<registry.password>default</registry.password>
  1. <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

六、参考

【1】不要把大型 JAR 包放进 Docker 镜像
【2】案例spring-boot-docker-jib

原文地址:https://www.cnblogs.com/kancy/p/12842782.html