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:镜像名称,此处声明为变量,在各模块下单独定义即可
dockerDirectoryDockfile路径
serverId:对应maven setting.xml里的server配置,用于配置docker.io用户名、密码
maven setting.xml中配置

	<server>
		<id>my-docker-registry</id>
		<username>xxx</username>
		<password>xxx</password>
	</server>

pushImagebuild完后自动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(配置中心配置)

编排脚本

我们把编排脚本分成两部分

固定服务

这些服务不经常更新,比如注册中心配置中心xxlportainer

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消息类型 及消息的手动签收、持久化
  • 启动portainervisualizer管理监控服务
  • 使用自定义创建的网络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(首次登录自定义用户名密码)
portainer

visualizer

访问http//ip:9001查看visualizer
visualizer

xxl

xxlmanager节点上,portainer上可以看到xxl被映射到30000端口
xxl
访问http://managerip:30000
xxl
创建调度器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

猜你喜欢

转载自blog.csdn.net/weixin_42189048/article/details/106412889