docker swarm实现java项目的发布/滚动更新/回滚/镜像管理

时间:2021-12-30 02:35:19

使用docker swarm滚动更新java项目,部署集群,这一切的前提是使用Jenkins+maven进行项目打包,分发等功能

具体可以参考我的另外三篇文章

https://www.cnblogs.com/mumengyun/p/10037246.html

https://www.cnblogs.com/mumengyun/p/10000739.html

https://www.cnblogs.com/mumengyun/p/10143203.html

以下写的就是如何使用docker swarm进行java项目的发布,滚动更新,回滚,镜像管理

大致的流程:
对打包好的jar包制作镜像-->上传到私服-->集群拉取镜像-->根据docker-compose.yaml文件创建swarm集群

Dockerfile文件
FROM x.x.x.x/java:8-jre
MAINTAINER xxx xxxx <xxxx@163.com>

LABEL image_category="fwx"

ADD ./jar/xxx.jar /app/

CMD ["java", "-Xmx1000m", "-jar", "/app/xxx.jar"]

x.x.x.x 这个IP为docker私有仓库的地址

LABEL标签 是为了删除未使用镜像的标签,当然作用不仅仅只这一个,后面的jenkins.sh脚本会使用这个标签

jenkins.sh内容
#!/bin/bash

# set -e
export BUILD_ID=dontkillme

\cp -f $WORKSPACE/target/fbl-findhousewx.jar /data/docker/findhousewx/jar && \

# 容器名称
CONTAINER="findhousewx"

# 服务名称
SERVICE_NAME="findhousewx_fbl-findhousewx-service"

# docker私有仓库的地址
REG_URL="x.x.x.x:8082/"

# 私有仓库账户密码
USER="admin"
PASSWD="fbl*#!"

# 登陆私有仓库
docker login -u $USER -p $PASSWD $REG_URL && \

# 镜像名称(以日期时间为镜像标签,防止重复)
IMAGE=$REG_URL$CONTAINER":"$(date -d "today" +"%Y%m%d_%H%M%S")

# dockerfile目录
cd /data/docker/findhousewx && \

# 创建新镜像
docker build -t $IMAGE . && \

# 上传镜像到私有仓库
docker push $IMAGE && \

echo "上传镜像完成" && \

# 定义删除未使用镜像和容器的函数
deletenotused(){
    # 删除未使用的pod
    docker container prune -f --filter "label=pod_category=fwx" --filter "until=48h"
    # 删除未使用的image(使用标签label来定位改服务的pod,防止删除其他服务的pod)
    docker image prune -a -f --filter "label=image_category=fwx" --filter "until=48h"
}
docker service ls | grep -i $CONTAINER
# 如果服务正在运行则滚动更新,如果没有就创建
if [ $? -eq 0 ];then
    # 滚动升级
    docker service update --image $IMAGE $SERVICE_NAME && \
    deletenotused
else
    # 删除 docker-compose.jenkins.yml 文件,防止使用相同镜像
    rm -rf docker-compose.yml && \

    # 复制 docker-compose.src.yml 文件,防止污染原文件
    cp docker-compose.src.yml docker-compose.yml && \

    # 替换镜像名标志位为最新镜像
    sed -i s%IMAGE_LATEST%$IMAGE%g docker-compose.yml && \

    # 使用 docker stack 启动服务
    docker stack deploy --with-registry-auth -c docker-compose.yml $CONTAINER && \

    deletenotused
fi
  1. export BUILD_ID=dontkillme 因为这个脚本实在jenkins中使用的,jenkins在执行完一项任务后,会将启动的进程杀掉,如果不加这个参数,在构建项目后,java -jar会退出

  2. 为什么要将镜像传到私有仓库?

    因为swarm集群的其他节点在启动容器时,也需要自己构建的镜像,这个镜像不能仅仅存在在manager节点上,worker上也需要能pull

  3. 定义删除未使用镜像和容器的函数

    函数的作用是删除未使用的镜像和exit状态的容器

    docker container prune -f --filter "label=pod_category=fwx" --filter "until=48h"

    删除有pod_category标签,且标签值为fwx;并且创建时间超过48小时的容器。 prune参数的作用是删除未运行的conrainer

    docker image prune -a -f --filter "label=image_category=fwx" --filter "until=48h"
    也是一样

  4. docker stack deploy --with-registry-auth -c docker-compose.yml $CONTAINER && \

    这里是重点啊!!! 这条命令是在最开始未创建服务的时候执行的,-c制定了docker-compose.yaml文件

    --with-registry-auth 这个是将docker login的登陆状态也传到swarm集群的其他节点。当创建一项服务的时候,各个节点第一步就是从docker私服仓库去拉取需要部署的镜像,但是我们只会在manager节点进行操作,docker login 也只会在manager节点进行登陆,那woker节点不登录肯定不能成功拉取镜像,这个参数就是来解决这个痛点的

docker-compose.src.yaml
version: '3'
services:
  fbl-findhousewx-service:
    image: IMAGE_LATEST
    labels:
       pod_category: fwx
       ismust: unnecessary
       branch: test
    hostname: fbl-findhousewx
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://baidu.com && exit 0 || exit 1"]
      interval: 10s
      timeout: 3s
      retries: 10
    deploy:
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 30s
      update_config:
        parallelism: 1
        delay: 15s
      mode: replicated
      replicas: 2
      labels:
        service_category: fwx
    environment:
      - TZ=Asia/Shanghai
    volumes:
      - /data/wwwlogs/:/data/wwwlogs/findhousewx
    ports:
      - 5020:5020
    restart: always
    networks:
      - fbl

networks:
   fbl:
     driver: overlay

这里说下LABEL:

在Dockerfile文件中的LABEL是images的标签

在docker-compose.yaml文件中services.fbl-findhousewx-service.labels是container的标签

在docker-compose.yaml文件中services.fbl-findhousewx-service.deploy.lebels是service的标签

也就是说镜像,容器,用容器启动的服务都有各自的标签

更多具体的可以学习官网的参考

主要是jenkins.sh这个脚本很重要!