微服务加速和简化构建Docker(基于Google jib)

准备

  • Maven3.5
  • Git
  • Jdk 1.8
  • Docker
$ git clone https://github.com/anjia0532/jib-demo.git
$ cd jib-demo
$ mvn clean package -DskipTests
$ mkdir docker
$ cp ./target/*.jar ./docker

Dockerfile

创建 ./docker/Dockerfile ,内容如下,需要注意此处为了方便理解,没有进行改进(比如限制用户,安装必要软件等)

FROM openjdk:8-jdk-alpine
ADD *.jar /app.jar
EXPOSE 8080
CMD java ${JAVA_OPTS} /app.jar

详情参见 官方文档 Dockerfile reference

$ cd ./docker
$ sudo docker build . -t jib-demo
$ docker images --查看本地images
$ docker tag jib-demo anjia0532/jib-demo --不写registry,则默认为docker hub registry,可以在build时,直接写
$ docker push anjia0532/jib-demo -- 推送到registry

小结

优点: 不需要改造pom,灵活,配合CI工具,可以不侵入项目,运维可以针对性的进行安全加固,并且可以做到标准化

缺点: 命令复杂,Java程序员需要学习Dockerfile命令,或者运维和java沟通不畅时,时区,软件,甚至目录等都可能有出问题

spotify/dockerfile-maven

需要注意,spotify/dockerfile-maven 是需要pom+Dockerfile一块用的,而docker-maven-plugin是可选的

在项目根目录创建Dockerfile,如下所示

FROM openjdk:8-jdk-alpine
EXPOSE 8080
ARG JAR_FILE
ADD target/${JAR_FILE} /usr/share/myservice/myservice.jar
ENTRYPOINT ["/usr/bin/java", "-jar", "/usr/share/myservice/myservice.jar"]

在pom里增加dockerfile-maven-plugin到build标签里

<build>
<plugins>
...
<plugin>
<groupid>com.spotify/<groupid>
<artifactid>dockerfile-maven-plugin/<artifactid>
<version>${dockerfile-maven-version}/<version>
<executions>
<execution>
default
<goals>
<goal>build/<goal>
<goal>push/<goal>
/<goals>
/<execution>
/<executions>
<configuration>
<repository>anjia0532/dockerfile-maven-demo/<repository>
${project.version}

<buildargs>
${project.build.finalName}.jar
/<buildargs>
/<configuration>
/<plugin>
...
<plugins>
<build>
/<build>/<plugins>/<plugins>/<build>

运行如下命令进行构建

$ mvn package -DskipTests

详情参见 官方文档 spotify/dockerfile-maven

小结

优点: 减少了docker build & tag & push 的操作,Java程序员能够控制镜像名

**缺点: **其实就是省了docker build & tag & push的操作,别的缺点一点没落不说,还得改动pom,还得要求写Dockerfile,tag只支持一个等等

Google jib

修改默认settings.xml,增加registry认证,参见Authentication Methods

<settings>
...
<servers>
...
<server>
docker_hub
<username>MY_USERNAME/<username>

<password>{MY_SECRET}/<password>
/<server>
/<servers>
/<settings>

改动pom.xml 增加 jib插件

<project>
...
<build>
<plugins>
...
<plugin>
<groupid>com.google.cloud.tools/<groupid>
<artifactid>jib-maven-plugin/<artifactid>
<version>1.0.0/<version>
<configuration>
<from>

<image>registry.hub.docker.com/hengyunabc/arthas:latest/<image>
<credhelper>docker_hub/<credhelper>
/<from>

<image>${project.artifactId}/<image>
<tags>
latest
${project.version}
/<tags>

<container>
<mainclass>${start-class}/<mainclass>
<ports>
<port>8080/<port>
<port>5701/udp/<port>
<port>8563/<port>
/<ports>
<entrypoint>
<shell>sh/<shell>
<option>-c/<option>
java -cp /app/resources/:/app/classes/:/app/libs/* com.example.demo.DemoApplication

/<entrypoint>
<approot>/app/<approot>
<usecurrenttimestamp>true/<usecurrenttimestamp>
/<container>
/<configuration>
/<plugin>
...
/<plugins>
/<build>
...
/<project>

执行mvn clean compile jib:dockerBuild 构建docker镜像

注意:

pom中用的是 registry.hub.docker.com/hengyunabc/arthas:latest 是 alibaba/arthas (阿里开源的一个Java诊断工具,便于线上调试)封装的docker镜像,如果不需要可以改成 registry.hub.docker.com/openjdk:8-jdk-alpine

$ docker run -d --init -p8563:8563 --name demo demo:latest
## 下面是启动arthas,如果使用的是openjdk镜像请勿执行
$ docker exec -it demo /bin/sh
$ jid=$(jps | grep App | awk '{print $1}')
$ java -jar /opt/arthas/arthas-boot.jar --target-ip 0.0.0.0 ${jid}

如果使用了arthas镜像,可以访问 http://ip:8563 ,在页面上填上宿主ip,点击Connect, 然后参考Arthas/命令列表 了解Arthas命令用法

微服务加速和简化构建Docker(基于Google jib)

小结

优点: 充分利用缓存,加快构建,不强制依赖docker daemon,依赖简单(在maven或gradle增加插件即可)

缺点: 不支持Docker RUN 命令(jib官方建议将run封装到base镜像),对entrypoint和cmd支持不太好(alpine默认不支持多任务,跑java应用默认是pid 1 ,运行jmap等命令会报错,参考 jmap not happy on alpine )

jib 缓存策略

项目每次发布实际上变更的代码量不大,尤其依赖的jar变动的可能性较小,如果按照前两种方案构建镜像,会导致每次都全量构建,会导致存储和带宽资源浪费。

Jib 如何让开发变得更美好

Jib 利用了 Docker 镜像的分层机制,将其与构建系统集成,并通过以下方式优化 Java 容器镜像的构建:

  • 简单——Jib 使用 Java 开发,并作为 Maven 或 Gradle 的一部分运行。你不需要编写 Dockerfile 或运行 Docker 守护进程,甚至无需创建包含所有依赖的大 JAR 包。因为 Jib 与 Java 构建过程紧密集成,所以它可以访问到打包应用程序所需的所有信息。在后续的容器构建期间,它将自动选择 Java 构建过的任何变体。
  1. 快速——Jib 利用镜像分层和注册表缓存来实现快速、增量的构建。它读取你的构建配置,将你的应用程序组织到不同的层(依赖项、资源、类)中,并只重新构建和推送发生变更的层。在项目进行快速迭代时,Jib 只讲发生变更的层(而不是整个应用程序)推送到注册表来节省宝贵的构建时间。
  2. 可重现——Jib 支持根据 Maven 和 Gradle 的构建元数据进行声明式的容器镜像构建,因此,只要输入保持不变,就可以通过配置重复创建相同的镜像。

可以可以通过 mvn clean compile jib:buildTar 生成 target/jib-image.tar 然后用解压缩工具解压后进行分析,实际上jib会将lib中非快照部分放到一个层,将快照部分放到一个层,将源码编译后放到一个层。。。

微服务加速和简化构建Docker(基于Google jib)

关注我:私信回复“555”获取往期Java高级架构资料、源码、笔记、视频Dubbo、Redis、Netty、zookeeper、Spring cloud、分布式、高并发等架构技术往期架构视频截图


分享到:


相關文章: