maven整合docker插件发布、部署springcloud项目
前言
想搭建这样一套体系:
- 项目代码更新
- 通过maven插件构建docker镜像、发布
- docker更新镜像、部署。
项目结构
案例是之前整合activemq的测试工程,结构如下
- 注册中心
- 配置中心
- 网关中心
- xxl-job-admin
- 消息发送服务
- 消息接收服务
- 中间件activemq
maven整合docker插件
我们使用docker-maven-plugin,在顶层pom定义
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<dockerHost>http://10.18.32.215:2375</dockerHost>
<imageName>${imageName}</imageName>
<dockerDirectory>${basedir}</dockerDirectory>
<serverId>my-docker-registry</serverId>
<pushImage>true</pushImage>
</configuration>
</plugin>
dockerHost:docker地址,默认localhost:2375
imageName:镜像名称,此处声明为变量,在各模块下单独定义即可
dockerDirectory:Dockfile路径
serverId:对应maven setting.xml里的server配置,用于配置docker.io用户名、密码
maven setting.xml中配置
<server>
<id>my-docker-registry</id>
<username>xxx</username>
<password>xxx</password>
</server>
pushImage:build完后自动push
eureka
pom
<properties>
<imageName>shuiniudocker/my-eureka:${version}</imageName>
</properties>
Dockerfile
FROM openjdk:8-jre-slim
MAINTAINER xsn
ENV PARAMS = "--spring.profiles.active=docker"
ADD target/eureka-*.jar /app.jar
ENTRYPOINT ["sh","-c","java -jar /app.jar $PARAMS"]
application-docker.yml
eureka:
instance:
prefer-ip-address: true
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://${EUREKA_SERVER}:10101/eureka
server:
enable-self-preservation: false
spring:
cloud:
inetutils:
preferred-networks: 192.168.0
${EUREKA_SERVER}是我们定义的注册地址变量,在编排文件中赋值。
关于
spring:
cloud:
inetutils:
preferred-networks: 192.168.0
这段配置是为了解决swarm下实例注册ip错误的问题,详情可查看另一篇文章
关于docker swarm部署springcloud 服务注册实例ip的问题
发布镜像
先mvn clean install后使用docker插件发布
发布完后可以登录dockerhub查看
config
pom
<properties>
<imageName>shuiniudocker/my-config:${version}</imageName>
</properties>
Dockerfile
FROM openjdk:8-jre-slim
MAINTAINER xsn
ENV PARAMS = "--eureka.client.service-url.defaultZone=http://my-eureka1:10101/eureka,http://my-eureka2:10101/eureka --spring.cloud.inetutils.preferred-networks=192.168.0"
ADD target/config-*.jar /app.jar
ENTRYPOINT ["sh","-c","java -jar /app.jar $PARAMS"]
指定注册中心集群地址
application.yml
#服务名端口号
server:
port: 10201
#Spring相关配置
spring:
application:
name: config
cloud:
config:
server:
git:
uri: https://github.com/dangzhicairang/my-config.git
username: xxx
password: xxx
search-paths: my-cloud
#服务注册中心
eureka:
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.hostname}:${random.int}
client:
#注册url
service-url:
defaultZone: http://localhost:10101/eureka
#开启所有监控中心接口
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: ALWAYS
实例名采用主机名+随机数的形式,避免同节点上的实例名重复
发布镜像
zuul
pom
<properties>
<imageName>shuiniudocker/my-zuul:${version}</imageName>
</properties>
Dockerfile
FROM openjdk:8-jre-slim
MAINTAINER xsn
ENV PARAMS = "--spring.profiles.active=docker"
ADD target/zuul-*.jar /app.jar
ENTRYPOINT ["sh","-c","java -jar /app.jar $PARAMS"]
bootstrap-docker.yml
spring:
#配置中心
cloud:
config:
profile: docker
discovery:
service-id: config
enabled: true
name: zuul
inetutils:
preferred-networks: 192.168.0
#服务注册中心
eureka:
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.hostname}:${random.int}
client:
#注册url
service-url:
defaultZone: ${EUREKA_SERVER_LIST}
发布镜像
xxl
pom
<properties>
<imageName>shuiniudocker/my-xxl:${version}</imageName>
</properties>
Dockerfile
FROM openjdk:8-jre-slim
MAINTAINER xsn
ENV PARAMS = "--spring.profiles.active=docker"
ADD target/xxl-*.jar /app.jar
ENTRYPOINT ["sh","-c","java -jar /app.jar $PARAMS"]
application-docker.yml
spring:
datasource:
url: jdbc:mysql://mysql:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
username: hcp
password: Hcp@123_2020
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
hikari:
minimum-idle: 10
maximum-pool-size: 30
auto-commit: true
idle-timeout: 3000
pool-name: dd
max-lifetime: 90000
connection-timeout: 1000
connection-test-query: SELECT 1
cloud:
inetutils:
preferred-networks: 192.168.0
eureka:
client:
serviceUrl:
defaultZone: ${EUREKA_SERVER_LIST}
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.hostname}:${random.int}
mysql使用接入同一docker网络的名为mysql的容器
发布镜像
activemq-provider
pom
<properties>
<imageName>shuiniudocker/${artifactId}:${version}</imageName>
</properties>
Dockerfile
FROM openjdk:8-jre-slim
MAINTAINER xsn
ENV PARAMS = "--server.port=0 --spring.profiles.active=docker"
ADD target/activemq-provider-*.jar /app.jar
ENTRYPOINT ["sh","-c","java -jar /app.jar $PARAMS"]
启动任意端口,由集群管理,通过网关访问即可
bootstrap-docker.yml
eureka:
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.hostname}:${random.int}
client:
service-url:
defaultZone: ${EUREKA_SERVER_LIST}
spring:
cloud:
config:
profile: docker
discovery:
service-id: config
enabled: true
name: activemq-provider, mq, xxl
inetutils:
preferred-networks: 192.168.0
activemq-consumer
pom
<properties>
<imageName>shuiniudocker/${artifactId}:${version}</imageName>
</properties>
Dockerfile
FROM openjdk:8-jre-slim
MAINTAINER xsn
ENV PARAMS = "--server.port=0 --spring.profiles.active=docker"
ADD target/activemq-consumer-*.jar /app.jar
ENTRYPOINT ["sh","-c","java -jar /app.jar $PARAMS"]
bootstrap-docker.yml
eureka:
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.hostname}:${random.int}
client:
service-url:
defaultZone: ${EUREKA_SERVER_LIST}
spring:
cloud:
config:
profile: docker
discovery:
service-id: config
enabled: true
name: activemq-consumer, mq
inetutils:
preferred-networks: 192.168.0
业务代码
@XxlJob("sendQueueText")
public ReturnT<String> sendQueueText(String param) {
sendService.sendQueueText("queue text: " + param);
return ReturnT.SUCCESS;
}
整合xxl模拟定时发消息,调度器为default(配置中心配置)
编排脚本
我们把编排脚本分成两部分
固定服务
这些服务不经常更新,比如注册中心、配置中心、xxl、portainer等
version: "3"
services:
my-eureka1:
ports:
- "10101"
deploy:
replicas: 1
placement:
constraints: [node.role == worker]
restart_policy:
condition: on-failure
image: shuiniudocker/my-eureka:1.0
environment:
- "EUREKA_SERVER=my-eureka2"
my-eureka2:
ports:
- "10101"
deploy:
replicas: 1
placement:
constraints: [node.role == worker]
restart_policy:
condition: on-failure
image: shuiniudocker/my-eureka:1.0
environment:
- "EUREKA_SERVER=my-eureka1"
my-config:
ports:
- "10201"
deploy:
replicas: 2
placement:
constraints: [node.role == worker]
restart_policy:
condition: on-failure
image: shuiniudocker/my-config:1.0
depends_on:
- my-eureka1
- my-eureka2
mysql:
ports:
- "3306:3306"
deploy:
replicas: 1
placement:
constraints: [node.role == manager]
restart_policy:
condition: on-failure
image: mysql:5.5
volumes:
- "/home/docker/volumes/mysql/logs:/logs"
- "/home/docker/volumes/mysql/data:/var/lib/mysql"
environment:
- "MYSQL_ROOT_PASSWORD=123456"
my-xxl:
ports:
- "10310"
deploy:
replicas: 1
placement:
constraints: [node.role == manager]
restart_policy:
condition: on-failure
image: shuiniudocker/my-xxl:1.0
environment:
- "EUREKA_SERVER_LIST=http://my-eureka1:10101/eureka,http://my-eureka2:10101/eureka"
depends_on:
- my-eureka1
- my-eureka2
- mysql
activemq:
ports:
- "8161:8161"
- "61616:61616"
deploy:
replicas: 1
placement:
constraints: [node.role == manager]
restart_policy:
condition: on-failure
image: webcenter/activemq
volumes:
- "/home/docker/volumes/activemq:/data/activemq/conf"
portainer:
image: portainer/portainer
ports:
- "9000:9000"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints: [node.role == manager]
visualizer:
image: dockersamples/visualizer:stable
ports:
- "9001:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints: [node.role == manager]
networks:
default:
external:
name: test-swarm
- 启动两个eureka搭建高可用的注册中心,赋值
EUREKA_SERVER
变量注定注册中心 - 其他服务部署在manager节点上
- activemq将自定义的配置文件(持久化配置、死信策略)挂载到容器内,如果需要可以进行替换重启
关于上述配置需求可参考
springboot整合activemq queue topic消息类型 及消息的手动签收、持久化 - 启动portainer和visualizer管理监控服务
- 使用自定义创建的网络test-swarm,指定了子网范围与前文提到的
spring.cloud.inetutils.preferred-networks
配置相关
#创建网络
docker network create -d overlay --attachable --subnet=192.168.0.0/24 test-swarm
其他服务
version: "3"
services:
my-zuul:
ports:
- "10302"
deploy:
replicas: 1
placement:
constraints: [node.role == worker]
restart_policy:
condition: on-failure
image: shuiniudocker/my-zuul:1.0
environment:
- "EUREKA_SERVER_LIST=http://my-eureka1:10101/eureka,http://my-eureka2:10101/eureka"
activemq-provider:
deploy:
replicas: 2
placement:
constraints: [node.role == worker]
restart_policy:
condition: on-failure
image: shuiniudocker/activemq-provider:1.0
environment:
- "EUREKA_SERVER_LIST=http://my-eureka1:10101/eureka,http://my-eureka2:10101/eureka"
activemq-consumer:
deploy:
replicas: 2
placement:
constraints: [node.role == worker]
restart_policy:
condition: on-failure
image: shuiniudocker/activemq-consumer:1.0
environment:
- "EUREKA_SERVER_LIST=http://my-eureka1:10101/eureka,http://my-eureka2:10101/eureka"
networks:
default:
external:
name: test-swarm
- 赋值
EUREKA_SERVER_LIST
指定注册中心地址 - 消息发送和接收服务各启动两个
测试
启动
docker stack deploy my-cloud -c docker-stack.yml
potainer
访问http//ip:9000查看portainer(首次登录自定义用户名密码)
visualizer
访问http//ip:9001查看visualizer
xxl
xxl在manager节点上,portainer上可以看到xxl被映射到30000端口
访问http://managerip:30000
创建调度器default
创建任务(bean模式,sendQueueText)
以上两步不了解的可参考该文https://blog.csdn.net/weixin_42189048/article/details/106402875
执行一次(发送一条测试消息)
验证
- 打开provider日志查看是否轮询调度消息发送服务
- 打开consumer日志查看消息消费服务是否轮询接受消息
验证通过,不再一一截图
测试镜像更新
简单修改consumer逻辑
发布镜像mvn clean insatll,docker build
发布完后在portainer更新服务,选择拉取最新镜像
重复测试步骤
验证结果
完美
总结
如此,我们的发布部署过程十分轻松,开发后直接通过开发工具整合的maven插件推送镜像,然后服务端通过portainer滚动更新(用户无察觉)
资料
源码地址
https://github.com/dangzhicairang/my-cloud.git
配置中心地址
https://github.com/dangzhicairang/my-config.git