Gitlab+Jenkins+docker完成Maven项目的自动部署

工程自动化开发环境搭建:Gitlab+Jenkins+docker如何来构建Maven项目

本文的环境:
Ubuntu 16.04LTS
Docker version 1.12.5, build 7392c3b

思路: Jenkisn安装在宿主机上,通过Jenkins从属机来拉取gitlab上的代码,进行Maven编译,使用docker进行发布。

安装Jenkins

关于Docker的安装,国内用户建议使用以下脚本:

#!/bin/sh

mv /etc/apt/sources.list /etc/apt/sources.list.bak

cd /etc/apt/

cat > sources.list <<- EOF
deb-src http://archive.ubuntu.com/ubuntu xenial main restricted #Added by software-properties
deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted
deb-src http://mirrors.aliyun.com/ubuntu/ xenial main restricted multiverse universe #Added by software-properties
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted multiverse universe #Added by software-properties
deb http://mirrors.aliyun.com/ubuntu/ xenial universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe
deb http://mirrors.aliyun.com/ubuntu/ xenial multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse #Added by software-properties
deb http://archive.canonical.com/ubuntu xenial partner
deb-src http://archive.canonical.com/ubuntu xenial partner
deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted multiverse universe #Added by software-properties
deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-security multiverse

EOF

apt-get update

curl -sSL https://get.daocloud.io/docker | sh

curl -L https://get.daocloud.io/docker/compose/releases/download/1.12.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

chmod +x /usr/local/bin/docker-compose

可以选择官方的Docker镜像。

docker run -p 8080:8080 -p 50000:50000 jenkins

不过没有本地环境,如果需要在Jenkins的宿主机上跑docker的话可以使用如下镜像包:

建议使用我写的安装包,包含JAVA与maven环境:

 docker run -it -d -p 8080:8080 -v /opt/jenkins:/jenkins -v /etc/localtime:/etc/localtime:ro --name jenkins lw96/java8-jenkins-maven-git-vim

这个包里面包含的环境:

  • Ubuntu 16.04 LTS
  • Oracle Java 1.8.0_112-b15 64 bit
  • Maven 3.3.9
  • Jenkins 2.19.4
  • git 2.7.4
  • Vim

不定期进行更新到最新的Jenkins,欢迎大家下载点星。

添加从属机与权限

系统管理→管理节点→新建节点

选择节点名称:选择Permament Agent

# of exectors 并发数 看你从属机的配置了
远程工作目录:  /opt/jenkins_workspace
标签:		  	SlaveServer
用法: 		尽可能的使用这个节点
启用方法:	   Launch slave agents via SSH
    Host: www.example.com
    Credentials: 点击Add添加,或者选择一个SSHkey
Availability:  keep this agent online as much as possible

上面的配置基本完成了一个从属机器的连接配置信息。

关于SSH登录与配置,点击我

下面的Node Properties中Environment variables为环境变量,Tools Locations为一些环境:

比如我的是这样填的:

git-2.7.4  /usr/bin/git
Docker     /usr/bin/docker
Maven3.3.9 /opt/maven
Java8	   /opt/java

以上路径为slave机上的环境。

我写了一个简单的安装shell脚本:

apt-get update 

apt-get install -y wget

export MAVEN_NAME=apache-maven-3.3.9
export MAVEN_HOME=/opt/maven/

wget --no-verbose -O /tmp/$MAVEN_NAME.tar.gz http://archive.apache.org/dist/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz \
    && mkdir /opt/maven \
    && tar -zxf /tmp/$MAVEN_NAME.tar.gz -C /opt/maven --strip-components=1 \
    && ln -s /opt/maven/bin/mvn /usr/local/bin \
    && rm -f /tmp/$MAVEN_NAME.tar.gz

apt-get install -y git

wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie"  -O /tmp/jdk-8u112-linux-x64.tar.gz http://download.oracle.com/otn-pub/java/jdk/8u112-b15/jdk-8u112-linux-x64.tar.gz \
    && mkdir /opt/java \
    && tar -zxf /tmp/jdk-8u112-linux-x64.tar.gz -C /opt/java/ --strip-components=1 \ 
    && update-alternatives --install /usr/bin/java java  /opt/java/bin/java 20000 \
    && update-alternatives --install /usr/bin/javac javac  /opt/java/bin/javac 20000  

点击保存。

新建任务

我的工作目录:

mkdir /opt/jenkins_workspace
cd /opt/jenkins_workspace
# 用来拉取gitlab代码,并编译用
mkdir workspace
# 用来存项目的war包与发布用
mkdir war	

(1)回到Jenkins首页,点击新建任务,选择自动风格。

General部分选择Restrict where this project can be run:

输入前面写的从属机的标签:SlaveServer

(2)源码管理,点击Git:

填入Repository URL仓库地址:比如ssh://www.example.com/test.git

选择之前添加的密钥,同理,把密钥添加到gitlab项目中。

点击高级,选择Name为origin

下面的分支选择origin/dev

(3)构建触发器:

选择Build when a change is pushed to Gitlab. Gitlab CI Service URL:http://jenkins.example.com:8080/project/projectName

取消 Comments前面的勾。其他可以根据自己的需要调整。

在Gitlab中,进入项目中,选择项目设置webhook→Url处填入上面的URL。

这样就完成了项目的自动触发。

(4)构建
添加Maven构建War包:

选择MavenVersion→命令:clean install→POM:pom.xml

选择Exectue Shell

cd /opt/jenkins_workspace && ./del.sh test 10000

其中del.sh脚本中的内容如下:

大体思想是,传递两个参数,一个是项目名称,一个项目运行的端口。

先去判断有没有这个同名容器,如果有,那就删除这个容器。

再去判断有没有端口被其他应用占用,如果没有,就运行容器;如果有,就在端口池里面随机一个端口进行运行容器。

#!/bin/bash

CONTAINER=$1
PORT=$2
MAXPORT=10000
MINPORT=20000
DIR="`dirname $BASH_SOURCE`"
MYDIR=`readlink -f "$DIR"`
# MYDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
echo $MYDIR

# functions 
# docker function
start_docker(){

filePath=$MYDIR/war/$CONTAINER

echo "docker use filePath is $filePath"

docker run -it -d --name $CONTAINER -p $PORT:8080 -v $filePath:/usr/local/tomcat/webapps tomcat:7-jre8

}

#check docker exist
check_docker(){

RUNNING=$(docker inspect --format="{{ .State.Running }}" $CONTAINER 2> /dev/null)

if [ $? -eq 1 ]; then
  echo "$CONTAINER does not exist."
  return 1
fi

if [ "$RUNNING" == "false" ]; then
  echo "$CONTAINER is not running."
  return 2
else
  echo "$CONTAINER is running"
fi

}

# check port
check_port() {
  echo "Checking instance port ..."
  netstat -tlpn | grep "\b$1\b"
}

#random a number
rand(){  
    min=$1  
    max=$(($2-$min+1))  
    num=$(cat /dev/urandom | head -n 10 | cksum | awk -F ' ' '{print $1}')  
    echo $(($num%$max+$min))  
}  

# delete same name container
matchingStarted=$(docker ps --filter="name=$CONTAINER" -q | xargs)
[[ -n $matchingStarted ]] && docker stop $matchingStarted

matching=$(docker ps -a --filter="name=$CONTAINER" -q | xargs)
[[ -n $matching ]] && docker rm $matching

# create warfile dir

cd `dirname $0`/war

if [ ! -d `pwd`/$1 ]; 
then
  mkdir $1
else
  rm -rf $1/*
  echo "`dirname $0`/workspace/$1/target/"
  cp $MYDIR/workspace/$1/target/*.war `pwd`/$1/$1.war
fi

# check port 
if check_port $PORT
then 
    PORT=$(rand $MINPORT $MAXPORT)
    while check_port $PORT 
    do
        PORT=$(rand $MINPORT $MAXPORT)
    done
fi
echo  "use $PORT to start $1 docker"

start_docker

echo "docker has started, waiting for tomcat.End!"

exit 0

(5)保存,Have Fun