写点什么

docker-compose 下的 java 应用启动顺序两部曲之二:实战

用户头像
极客good
关注
发布于: 刚刚

</parent>


<properties>


<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>


<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>


<java.version>1.8</java.version>


<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>


</properties>


<dependencies>


<dependency>


<groupId>org.springframework.cloud</groupId>


<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>


</dependency>


</dependencies>


<build>


<plugins>


<plugin>


<groupId>org.springframework.boot</groupId>


<artifactId>spring-boot-maven-plugin</artifactId>


</plugin>


<plugin>


<groupId>com.google.cloud.tools</groupId>


<artifactId>jib-maven-plugin</artifactId>


<version>1.7.0</version>


<configuration>


<from>


<image>openjdk:8-jdk-stretch</image>


</from>


<to>


<image>bolingcavalry/{project.version}</image>


</to>


<container>


<jvmFlags>


<jvmFlag>-Xms1g</jvmFlag>


<jvmFlag>-Xmx1g</jvmFlag>


</jvmFlags>


<ports>


<port>8080</port>


</ports>


<useCurrentTimestamp>true</useCurrentTimestamp>


</container>


</configuration>


<executions>


<execution>


<phase>compile</phase>


<goals>


<goal>dockerBuild</goal>


</goals>


</execution>


</executions>


</plugin>


</plugins>


</build>


</project>


上述 pom.xml 中多了个 jib 插件,这样在执行 mvn compile 的时候,插件就会用构建结果制作好 docker 镜像并放入本地仓库;


2. service 是个普通的 SpringCloud 应用,除了在 pom.xml 中也用到了 jib 插件来构建镜像,它的配置文件中,访问 eureka 的地址要写成 eureka 容器的名称:


spring:


application:


name: service


eureka:


client:


serviceUrl:


defaultZone: http://eureka:8080/eureka/


  1. 关于如何将 java 应用制作成 docker 镜像,如果您想了解更多请参考以下两篇文章:


《Docker与Jib(maven插件版)实战》


《Jib使用小结(Maven插件版)》

制作基础镜像

从上面的 pom.xml 可见,我们将 Java 应用制作成 docker 镜像时,使用的基础镜像是 openjdk:8-jdk-stretch,这样做出的应用镜像是不含 wait-for-it.sh 脚本的,自然就无法实现启动顺序控制了,因此我们要做一个带有 wait-for-it.sh 的基础镜像给业务镜像用:


  1. 把 wait-for-it.sh 文件准备好,下载地址:https://raw.githubusercontent.com/zq2599/blog_demos/master/wait-for-it-demo/docker/wait-for-it.sh

  2. 在 wait-for-it.sh 文件所在目录新建 Dockerfile 文件,内容如下:


FROM openjdk:8-jdk-stretch


ADD wait-for-it.sh /wait-for-it.sh


RUN sh -c 'chmod 777 /wait-for-it.sh'


注意:我这里用的是 openjdk:8-jdk-stretch,您可以根据自己的实际需要选择不同的 openjdk 版本,可以参考:《openjdk镜像的tag说明》


  1. 执行命令 docker build -t bolingcavalry/jkd8-wait-for-it:0.0.2 .就能构建出名为 bolingcavalry/jkd8-wait-for-it:0.0.2 的镜像了,请您根据自己的情况设置镜像名称和 tag,注意命令的末尾有个小数点,不要漏了;

  2. 如果您有 hub.docker.com 账号,建请使用 docker push 命令将新建的镜像推送到镜像仓库上去,或者推送到私有仓库,因为后面使用 jib 插件构建镜像是,jib 插件要去仓库获取基础镜像的元数据信息,取不到会导致构建失败;

使用新的基础镜像构建 service 镜像

我们的目标是让 service 服务等待 eureka 服务就绪,所以应该改造 service 服务,让它用 docker 官方推荐的 wait-for-it.sh 方案来实现等待:


  • 修改 service 工程的 pom.xml,有关 jib 插件的配置改为以下内容:


<plugin>


<groupId>com.google.cloud.tools</groupId>


<artifactId>jib-maven-plugin</artifactId>


<version>1.7.0</version>


<configuration>


<from>


<image>bolingcavalry/jkd8-wait-for-it:0.0.2</image>


</from>


<to>


<image>bolingcavalry/{project.version}</image>


</to>


<container>


<entrypoint>INHERIT</entrypoint>


<ports>


<port>8080</port>


</ports>


<useCurrentTimestamp>true</useCurrentTimestamp>


</container>


</configuration>


<executions>


<execution>


<phase>compile</phase>


<goals>


<goal>dockerBuild</goal>


</goals>


</execution>


</executions>


</plugin>


上述配置有几点需要注意:


a. 基础镜像改为刚刚构建好的 bolingcavalry/jkd8-wait-for-it:0.0.2


b. 增加 entrypoint 节点,内容是 INHERIT,按照官方的说法,entrypoint 的值等于 INHERIT 表示 jib 插件不构建启动命令了,此时要使用者自己控制,可以在启动时输入,或者写在基础镜像中,这样我们在 docker-compose.yml 中用 command 参数来设置 service 容器的启动命令,就可以把 wait-for-it.sh 脚本用上了


c. 去掉 jvmFlags 节点,按照官方文档的说法,entrypoint 节点的值等于 INHERIT 时,jvmFlags 和 mainClass 参数会被忽略,如下图,地址是:https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin



至此,service 工程改造完毕,接下来修改 docker-compose.yml,让 service 容器能用上 wait-for-it.sh

改造 docker-comp

【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


ose.yml


  1. 完整的 docker-compose.yml 内容如下所示:


version: '3'


services:


eureka:


image: bolingcavalry/eureka:0.0.1-SNAPSHOT


container_name: eureka


restart: unless-stopped


service:


image: bolingcavalry/service:0.0.1-SNAPSHOT


container_name: service


restart: unless-stopped


command: sh -c './wait-for-it.sh eureka:8080 -t 0 -- java -Xms1g -Xmx1g -cp /app/resources:/app/classes:/app/libs/* com.bolingcavalry.waitforitdemo.ServiceApplication'


depends_on:


  • eureka


  1. 注意 command 参数的内容,如下,service 容器创建后,会一直等待 eureka:8080 的响应,直到该地址有响应后,才会执行命令 java -Xms1g -Xmx1g -cp /app/resources:/app/classes:/app/libs/* com.bolingcavalry.waitforitdemo.ServiceApplication:


sh -c './wait-for-it.sh eureka:8080 -t 0 -- java -Xms1g -Xmx1g -cp /app/resources:/app/classes:/app/libs/* com.bolingcavalry.waitforitdemo.ServiceApplication'


  1. 对于命令 java -Xms1g -Xmx1g -cp /app/resources:/app/classes:/app/libs/* com.bolingcavalry.waitforitdemo.ServiceApplication,您可能觉得太长了不好写,这里有个小窍门,就是在不使用 entrypoint 节点的时候,用 jib 插件制作的镜像本身是带有启动命令的,容器运行的时候,您可以通过 docker ps --no-trunc 命令看到该容器的完整启动命令,复制过来直接用就行了;


所有的改造工作都完成了,可以开始验证了;

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
docker-compose下的java应用启动顺序两部曲之二:实战