使用google jib实现java应用快速容器化

前天(2018年7月9日),谷歌宣布将其内部使用的 jib 正式开源。jib 是一个在 java 体系内部生成 docker 镜像的插件,它的设计初衷是将代码->可运行程序->docker image整个过程打通,无需编写 docker file,直接通过编译器生成 docker 镜像。因为刚出来,中文资料比较少,我撸了一个样例,第一时间体验一下这个新玩意。以下是整个过程。

环境说明

我选定的是一个maven构建的spring boot项目,编译后是一个内嵌 tomcat 的可执行jar。目标是通过引入jib,直接生成该项目的镜像发布到阿里云镜像仓库。

引入依赖

jib最新版本是0.9.4。通过在pom.xmlplugins标签下增加jib标签,引入依赖。

1
2
3
4
5
6
7
8
9
<build>
<plugins>
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>0.9.4</version>
</plugin>
</plugins>
</build>

当在IDEA的右侧Maven Projects下的Plugins里看到jib时,代表这一步OK了。

配置镜像仓库

在maven的配置文件 settings.xml 中,增加阿里云镜像仓库的信息。如下:

1
2
3
4
5
6
7
<servers>
<server>
<id>registry.cn-hangzhou.aliyuncs.com</id>
<username>你的阿里云账号</username>
<password>你的阿里云密码</password>
</server>
</servers>

关于如何使用阿里云镜像仓库,可以参考我的另一篇文章。当然,不一定时阿里云镜像仓库,你可以使用其他的镜像中心,比如 docker hub。在国内阿里云更快。

配置编译参数

pom.xmljib的配置段中增加编译参数,如下例:

1
2
3
4
5
6
7
8
9
10
11
12
13
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>0.9.4</version>
<configuration>
<from>
<image>openjdk:alpine</image>
</from>
<to>
<image>registry.cn-hangzhou.aliyuncs.com/lefer/leferapi:1.2</image>
</to>
</configuration>
</plugin>

编译镜像

在右侧的Maven Projects里运行jib build。输出形如下面的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building api 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- jib-maven-plugin:0.9.4:build (default-cli) @ api ---
[INFO]
[INFO] Containerizing application to registry.cn-hangzhou.aliyuncs.com/lefer/leferapi:1.0...
[INFO]
[INFO] Retrieving registry credentials for registry.cn-hangzhou.aliyuncs.com...
[INFO] Getting base image openjdk:alpine...
[INFO] Building dependencies layer...
[INFO] Building resources layer...
[INFO] Building classes layer...
[INFO] Retrieving registry credentials for registry.hub.docker.com...
[INFO] Finalizing...
[INFO]
[INFO] Container entrypoint set to [java, -cp, /app/libs/*:/app/resources/:/app/classes/, com.lefer.ApiApplication]
[INFO]
[INFO] Built and pushed image as registry.cn-hangzhou.aliyuncs.com/lefer/leferapi:1.0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:18 min
[INFO] Finished at: 2018-07-12T00:54:24+08:00
[INFO] Final Memory: 19M/207M
[INFO] ------------------------------------------------------------------------
Process finished with exit code 0

镜像结构

jib生成的镜像,程序相关内容全部在/app路径下。下含classeslibsresources三个子目录。分别放置类文件、依赖文件、资源文件。application.properties也在resources目录中。

1
2
3
4
5
6
7
8
9
[web@localhost]$ tree -L 2 -d
.
|-- classes
| `-- com
|-- libs
`-- resources
`-- img
5 directories

事实上在本示例中jib生成的dockerfile的内容是这样的:

1
2
3
4
5
6
7
8
FROM openjdk:alpine
COPY libs /app/libs/
COPY resources /app/resources/
COPY classes /app/classes/
ENTRYPOINT ["java","-cp","/app/libs/*:/app/resources/:/app/classes/","com.lefer.ApiApplication"]
CMD []

测试镜像

我们将镜像pull下来试一下,能否正常使用。

1
2
3
4
5
6
7
8
9
10
# 由于我在阿里云镜像仓中设定是私有仓库,所以需要先login。如果是公有仓库,不需要此步。
docker login --username=aliyun账号 registry.cn-hangzhou.aliyuncs.com
docker pull registry.cn-hangzhou.aliyuncs.com/lefer/leferapi:1.2
docker run \
--name leferapi \
-e spring.data.mongodb.uri=mongodb://username:password@ip:port/db \
-v /home/web/mp3:/app/resources/static/mp3 \
-v /home/web/img:/app/resources/static/img \
-d -p 7014:7014 \
registry.cn-hangzhou.aliyuncs.com/lefer/leferapi:1.2

docker run命令里我使用-e覆写了application.properties里的spring.data.mongodb.uri配置项,使用-vjar里的两个静态资源目录映射到了宿主机。

测试一切正常!

总结

目前在pom.xml里写configuration实现镜像的生成,便于java程序员使用docker,简化了发布的流程。至少不用再维护一个docke file,让整个事件变得更简单。java当年就是以跨平台起家的,现在与docker结合,进一步增强了跨平台的能力。jib是个很好的脚手架,推荐大家一试。

END