本文是结合目前工作实际场景中,实现利用容器来构建docker+jenkins+git+registry进行项目的CI自动发布流程,从中也填过坑,不多。如有不实之处,欢迎指出,共同讨论。
-
流程设计
公司开发大脑×××同学呕心沥血、劈里啪啦地写了n堆代码,提交到代码仓库后,到能访问到他本人写的壮硕成果,一般会经历如下过程: -
环境
Jenkins安装,准备一台server,安装略,百度一下。
Docker安装,准备一台server,安装略,百度一下。
Git仓库,准备一台server,安装略,百度一下。 - Jenkins上配置
- 新建一Maven的Job项目。
- 新建一Maven的Job项目。
-
Jenkins配置-源码
-
Jenkins配置-构建触发器
-
Jenkins配置-构建环境
构建前,从集中存放配置文件的GitLab中拉取最新配置文件,包含Dockerfile,后面开始构建会引用最新文件。cd /data/httpd/release/b2b-configuration;git pull sleep 3; yes | cp -rfp /data/httpd/release/b2b-configuration/Spring-partner/QA/application.yml /home/jenkins/.jenkins/workspace/b2b-partner-test/src/main/resources/ yes | cp -rfp /data/httpd/release/b2b-configuration/Spring-partner/QA/logback-spring.xml /home/jenkins/.jenkins/workspace/b2b-partner-test/src/main/resources/ yes | cp -rfp /data/httpd/release/b2b-configuration/Spring-partner/QA/Dockerfile /home/jenkins/.jenkins/workspace/b2b-partner-test/
配置文件说明:
Dockerfile:FROM registry.cn-hangzhou.aliyuncs.com/xmbaby-pre/ms-jdk8 EXPOSE 8081 MAINTAINER b2b-partner-test hhyuking@yeah.net ADD b2b-partner.jar /data/httpd/ RUN mkdir -p /data/httpd/log/ WORKDIR /data/httpd/ ENTRYPOINT java -Xmx256m -Xss512k -jar b2b-partner.jar
application.yml:项目基本信息配置项,如数据库连接信息等。
logback-spring.xml:定义了spring-boot项目log日志信息,包含日志级别(info、error)、日志格式及在运行容器中log的存储目录等。<?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/base.xml" /> <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>INFO</level> </filter> <File>/data/logs/aa-b2b-partner_info.log</File> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>/data/httpd/log/aa-b2b-partner_info-%d{yyyyMMdd}.log.%i </fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> <maxHistory>0</maxHistory> </rollingPolicy> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern> </layout> </appender> <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>ERROR</level> </filter> <File>/data/logs/aa-b2b-partner_error.log</File> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>/data/httpd/log/aa-b2b-partner_error-%d{yyyyMMdd}.log.%i </fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> <maxHistory>0</maxHistory> </rollingPolicy> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern> </layout> </appender> <root level="INFO"> <appender-ref ref="ERROR_FILE" /> <appender-ref ref="INFO_FILE" /> </root> </configuration>
- Jenkins配置-构建和构建后操作
先同步jar包和Dockerfile到Docker那台server上,然后用expect交互命令将shell脚本发送到Docker那台server上,进行docker容器的构建、启动、push到阿里云镜像仓库等操作。
Jenkins这台server的rsync脚本:bash /home/jenkins/docker-test/script/b2b-rsync.sh b2b-partner-test 后带参数。
rsync同步脚本:#!/bin/bash IP=10.10.10.10 PASSWD=p@ssword1 echo -e "开始同步jar包..." rsync -vzrtopg --numeric-ids --progress --password-file=/etc/rsyncd.password6 /home/jenkins/.jenkins/workspace/$1/target/b2b-partner.jar root@$IP::$1 echo -e "开始同步Dockerfile..." rsync -vzrtopg --numeric-ids --progress --password-file=/etc/rsyncd.password6 /home/jenkins/.jenkins/workspace/$1/Dockerfile root@$IP::$1 expect /home/jenkins/docker-test/script/image_b2b.exp $IP $PASSWD $1
expect交互命令脚本:/home/jenkins/docker-test/script/image_b2b.exp
#!/usr/bin/expect -f set ipaddress [lindex $argv 0] set passwd [lindex $argv 1] set jobname [lindex $argv 2] spawn ssh xiaoyu@$ipaddress; expect "password:"; send "$passwd\r"; expect "#" send "sudo nohup /data/docker/layout-script/docker-qa.sh $jobname >> /data/docker/logs/$jobname.log &\r"
注意:执行上面expect脚本前,需将ssh的用户,到对方server的visudo配置中加入:xiaoyu ALL=(ALL) NOPASSWD: ALL, 要不然用户无法ssh过去。
- Docker配置
查看同步到Docker的Dockerfile,maven构建好的jar包也同步到此目录下。
root@docker-qa b2b-partner-test]# ll
总用量 61476
-rw-rw-r-- 1 1010 1010 62944090 Jul 26 19:46 b2b-partner.jar
-rw-rw-r-- 1 1010 1010 237 Jul 26 10:00 Dockerfile
关键在Docker server上执行的docker-qa.sh脚本
#!/bin/bash
JOBMS=$1
VERSION=latest
JOBREPO=/data/docker/$1
IMGREPO=xmbaby-test
IMGNAME=$1
DTIME=`date +%Y-%m-%d" "%H":"%M":"%S`
CONTAINER_NAME=b2b-partner-test-container
if [ ! -d $JOBREPO ];then
mkdir -p $JOBREPO
scp jenkins@10.10.10.10:~/.jenkins/workspace/$1/target/b2b-partner.jar $JOBREPO
scp jenkins@10.10.10.10:~/.jenkins/workspace/$1/Dockerfile $JOBREPO
echo -e "\n[$JOBMS]" >> /etc/rsyncd.conf
echo "path=/data/docker/$JOBMS/" >> /etc/rsyncd.conf
echo "comment = update
ignore errors
read only = no
list = no
hosts allow = 10.10.10.10/255.255.255.0
auth users = root
uid = root
gid = root
secrets file = /etc/rsyncd.secrets" >> /etc/rsyncd.conf
else
echo -e "\n时间$DTIME,开始构建docker镜像"
fi
#CID=$(docker ps | grep "$CONTAINER_NAME" | awk '{print $1}')
#IID=$(docker images | grep "$CONTAINER_NAME" | awk '{print $3}')
cd $JOBREPO
echo -e "构建docker镜像前,删除之前的容器、镜像."
IMAGE_ID=`docker images |grep "b2b-partner-img/$JOBMS" |awk '{print $3}'`
echo "Image镜像ID:$IMAGE_ID"
#CONTAINER_ID=`docker images |grep "b2b-partner-img/$JOBMS" |awk '{print $1}'`
CONTAINER_ID=`docker ps |grep $CONTAINER_NAME |awk '{print $NF}'`
echo "Container容器:$CONTAINER_ID"
docker rm -f $CONTAINER_ID | true
echo -e "$CONTAINER_ID 当前老容器删除成功!"
docker rmi -f $IMAGE_ID | true
echo -e "$IMAGE_ID 当前老镜像删除成功!"
echo -e "时间$DTIME,正式开始构建docker镜像"
docker build -t b2b-partner-img/$JOBMS .
if [ $? -ne 0 ];then
echo -e "时间$DTIME,$JOBMS 镜像构建失败,请检查dockerfile !"
exit
else
echo -e "时间$DTIME,开始运行Docker容器."
#docker run --name $CONTAINER_NAME -v $JOBREPO:$JOBREPO -d -p 8081:8081 b2b-partner-img/$JOBMS
docker run --name $CONTAINER_NAME -d -p 8081:8081 b2b-partner-img/$JOBMS
sleep 5
echo -e "时间$DTIME,$CONTAINER_NAME容器创建完成.开始推送到阿里镜像仓库中..."
IMAGEID_NEW=`docker images |grep "b2b-partner-img/$JOBMS" |awk '{print $3}'`
echo "New镜像ID:$IMAGEID_NEW"
CONTAINERID_NEW=`docker images |grep "b2b-partner-img/$JOBMS" |awk '{print $1}'`
echo "New Container容器:$CONTAINERID_NEW"
docker login --username=xiaoming --password=passwd registry.cn-hangzhou.aliyuncs.com
docker tag $IMAGEID_NEW registry.cn-hangzhou.aliyuncs.com/$IMGREPO/$IMGNAME:$VERSION
docker push registry.cn-hangzhou.aliyuncs.com/$IMGREPO/$IMGNAME:$VERSION
fi
-
Jenkins上构建
构建
Jenkins控制台查看构建log - 测试访问
要使用域名测试访问,由于Docker QA上80端口已被其他应用占用,故在一台Nginx服务上设置代理到容器的8081端口上,通过一接口进行域名访问,如下图所示,说明能通: