Jib

Jib工具是Google去年推出的针对java的Docker构建工具,Jib解决的问题比较明确,核心是Java镜像文件太大的问题。同时,用其作者的话,I'am a Java Developer, I don't want to have to care about Dockerfiles,Jib通过maven/gradle插件,可以帮助开发者不用写dockerfile就可以build出docker镜像。

Java镜像文件过大,原因包括如下两点:

  • Java运行需要JVM,启动需要JRE,Java的基础镜像非常大,比如openjdk基础镜像达到284M,Google的
    distroless,社区jre-alpine镜像都可以做到100M以内。基础镜像虽然大,但是由于docker的分层镜像机制,配置合适的拉取策略,基础镜像不变也不会增加额外的分发时间。
  • Java应用的镜像通常也非常大。我们现在通常将应用镜像打包层war, fat jar文件。Java生态的依赖关联作的不太好,加上集团内的富二方包的现状,通常app镜像在100M以上。Docker的unionfs虽然是分层的,但是war, fat jar作为一个读写层,任何一个资源文件或class文件的变更,都会导致该层md5变更,从而导致该层的重新拉取和替换。

原因二是需要重点解决的问题,解法也非常简单,借助docker的分层镜像机制,将app镜像进一步分层,结合java应用的特点,进一步分为三层:

  • dependencies
  • resources
  • classes

显然,经常变更的是resources, classes,但是其层镜像非常小。启动拉取时耗时非常短。

具体实现时,jib通过maven插件,实现了docker的pull和push机制,由于是maven插件,可以在maven编译期组织三类资源,然后生成dockerfile针对三类资源的COPY语句。

1
2
3
4
5
6
7
FROM [base image]

COPY libs [path/to/dependencies]
COPY resources [path/to/resources]
COPY classes [path/to/classes]

...

由于一个语句对应一个layer,因此自然实现了分层。

针对denpendencies层,由于snapshot经常发生变化,如果有大量的snapshot jar存在,denpendencies层也会被拉取替换,在具体实现时,可以针对snapshot再单独拉出一层,进一步降低拉取替换粒度。