嫌弃开发部署这一套流程过于麻烦,搞了一下Jenkins做CI\CD。需要实现的效果是:git仓库master分支提交代码,在Jenkins点击之后可以自动拉代码构建项目产出jar包、Dockerfile,自动做成镜像,最后自动部署到docker。本文假设你对Jenkins有所了解。

前言

像这样的东西原本应该是运维人员的事情。所以我个人认为开发者没必要会,浪费时间。当然你要是个卷王或者像我公司一样人员配置不健全那当我没说。

实现

1.docker环境准备:
安装docker:

sudo apt-get install docker.io

处理权限问题:在安装的时候会创建docker用户组,你需要将操作用户加入到这个用户组中

# sudo groupadd docker
sudo gpasswd -a username docker
sudo service docker restart

2.Jenkins环境准备
安装Jenkins:

docker run -d -p 8080:8080 -p 50000:50000 -v /home/username/data/jenkins:/var/jenkins_home jenkins/jenkins

注:正常情况下你应该规划和设置好服务的Volume与Network,在容器内部是使用root运行的,你应该自己创建好挂载工作目录,本文中/home/username/data/jenkins/secrets/initialAdminPassword文件可以获取安装密钥。具体部署Jenkins请查看参考文档
Jenkins插件依赖:在你选择安装默认插件还需要添加:SSH;它用来远程执行shell脚本。

3.准备Dockerfile/nginx.conf模板文件

FROM openjdk:8u292-jre

MAINTAINER tlrobot "coder@tlrobot.com"

RUN mkdir -p /data/#{APP_NAME}/

COPY #{JAR_NAME} /data/#{APP_NAME}/

EXPOSE 8080

CMD ["java","-jar","/data/#{APP_NAME}/#{JAR_NAME}","#{JVM_ARGS}","#{SPRING_ARGS}"]

注:这里我的处理方式是定义一个模板文件,然后命令行替换占位符生成应用专属Dockerfile。你可以参考这个处理方式处理nginx配置文件。

4.编写Jenkins pipeline
git拉取与maven构建就不再多说了,只有几个点需要注意的:在 系统管理-》全局工具配置 下面可以设置git,maven,在 系统管理-》系统配置 里面可以设置maven与git,也可以配置ssh所依赖的远端仓库。之后在pipeline配置仓库,maven goal就行。
添加一个执行shell的pipeline step。脚本内容如下:

# 创建Dockerfile

APP_NAME="TEST_APP"
CONTAINER_NAME=""
DEPLOY_PROFILE="test"
JVM_ARGS=""
SPRING_ARGS="spring.profiles.active=$DEPLOY_PROFILE"

TARGET_FOLDER="./target"

JAR_NAME="demo.jar"



if [ "$JVM_ARGS" = "" ]
then
    JVM_ARGS="-Xmx800M -Xmn350m -Xss256K -XX:MaxMetaspaceSize=150M -XX:MaxDirectMemorySize=100M"
fi

if [ "$CONTAINER_NAME" = "" ]
then
    CONTAINER_NAME=$APP_NAME
else
    CONTAINER_NAME=$CONTAINER_NAME
fi
# 找到构建好的jar
for name in `find $TARGET_FOLDER -name *.jar`
do
    echo "--------->>>>$name" 
    if [ "${name##*.}"x = "jar"x ]
    then
        JAR_NAME=${name##*/}
    fi
done 
# 替换占位符
awk  -v jar_name="$JAR_NAME" '{gsub("#{JAR_NAME}",jar_name);print $0}' $JENKINS_HOME/Dockerfile | awk -v jvm_args="$JVM_ARGS" '{gsub("#{JVM_ARGS}",jvm_args);print $0}' | awk -v spring_args="$SPRING_ARGS" '{gsub("#{SPRING_ARGS}",spring_args);print $0}' | awk -v app_name="$APP_NAME" '{gsub("#{APP_NAME}",app_name);print $0}' >> $TARGET_FOLDER/Dockerfile

#创建nginx.conf

添加一个远程执行shell的pipeline step。脚本内容如下:

# 构建image启动docker项目
#copy jar包到部署目

#目标机器的工作目录
JENKINS_WORKSPACE="/home/username/data/jenkins/workspace"
#项目名称:是构建名称而不是git仓库的名称,也不是maven项目名称。我们推荐他们三者应该保持一致。
PROJECT_NAME="deploy_test"
#Dockerfile与jar所在目录
TARGET_FOLDER="target"
JAR_NAME="demo.jar"
PORT=8080
LOG_FOLDER=/logs/$PROJECT_NAME

for name in `find $JENKINS_WORKSPACE/$PROJECT_NAME/$TARGET_FOLDER -name *.jar`
do
    echo "--------->>>>$name" 
    if [ "${name##*.}"x = "jar"x ]
    then
        JAR_NAME=${name##*/}
    fi
done 

#构建镜像
docker build -t tlrobot:$JAR_NAME $JENKINS_WORKSPACE/$PROJECT_NAME/$TARGET_FOLDER

#停止容器
DOCKERID=`docker ps --filter name=^/${JAR_NAME}$ | grep ${JAR_NAME} |awk '{print $1}'`
if [ "$DOCKERID" = "" ]
then
    echo "no docker container alive"
    DOCKERID=`docker ps -a --filter name=^/${JAR_NAME}$ | grep ${JAR_NAME} |awk '{print $1}'`
    if [ "$DOCKERID" = "" ]
    then
        echo "confirm no docker container"
    else
    docker rm $DOCKERID 
    fi
else
    docker stop $DOCKERID
    docker rm $DOCKERID
fi
# 启动容器
docker run -d --privileged -p $PORT:8080 --name $JAR_NAME -v $LOG_FOLDER:$LOG_FOLDER  -v /etc/hosts:/etc/hosts -v /data/cert:/data/cert  tlrobot:$JAR_NAME
DOCKERID=`docker ps --filter name=^/${JAR_NAME}$ | grep $JAR_NAME|awk '{print $1}'`
if [ "$DOCKERID" = "" ]
then
    echo -e "app start fail................."
    exit -1
else
    docker logs $DOCKERID
fi

注:远程执行shell需要你选择预先配置好的主机,在这里我们配置的是Jenkins外围的Docker主机。配置在 系统管理-》系统配置 。

总结:

本质上的流程这样的:从git拉取代码,maven打包产生jar文件,运行shell生成配置文件,在远端执行shell在docker主机上构建docker镜像(image),然后运行镜像。我是一个不支持内卷的人,我希望这样的事应该有运维处理。

标签: 持续集成, docker

添加新评论