在如今的互联网时代,随着软件开发复杂度的不断提高,软件开发和发布管理也越来越重要。目前已经形成一套标准的流程,最重要的组成部分就是持续集成(Continuous Integration,CI)及持续部署、交付(CD)。在此,我们来以一个案例初步了解 CI 流程。那么什么是 CI 呢?简单来讲,CI 就是将传统的代码合并、构建、部署、测试都集成在一起,不断地执行这个过程,并对结果进行反馈。 CI 流程设计图: 工作流程:

  1. 开发人员提交代码到Git版本仓库;
  2. Jenkins人工/定时触发项目构建;
  3. Jenkins拉取代码、代码编码、打包镜像、推送到镜像仓库;
  4. Jenkins在Docker主机创建容器并发布

服务器规划: IP地址 角色 192.168.30.21 Jenkins,Docker,JDK,Maven 192.168.30.22 Harbor(Docker,docker-compose),Git

1. 部署Git代码版本仓库 git是一个系统,但是没有守护进程,可以让ssh作为通信

[root@harbor-git ~]# yum install git -y
[root@harbor-git ~]# useradd git
[root@harbor-git ~]# passwd git

更改用户 git 的密码 。 新的 密码: 无效的密码: 密码是一个回文 重新输入新的 密码: passwd:所有的身份验证令牌已经成功更新。

然后通过这个Git远程操作这个仓库,一般git里面都加个.git

[root@harbor-git ~]# su - git
[git@harbor-git ~]$ mkdir demo.git

初始化这个git仓库,搭建完成

[git@harbor-git ~]$ cd demo.git/
[git@harbor-git demo.git]$ git --bare init

初始化空的 Git 版本库于 /home/git/demo.git/

现在开始使用,git可以当成客户端,也可以当成服务端来用 [root@jenkins ~]# yum install git -y

Jenkins主机测试访问该仓库:

[root@jenkins ~]# git clone git@192.168.30.22:/home/git/demo.git
正克隆到 'demo'...
git@192.168.30.22's password: 

warning: 您似乎克隆了一个空版本库。

 模拟生产项目,拉取github上的一个demo,并上传至本地git库 这里我是一个java的测试项目,然后演示一下 进入我们拉代码空仓库里,把我们的项目拷贝进去

[root@jenkins ~]#  git clone https://github.com/xxx/tomcat-java-demo.git

[root@jenkins ~]# cd demo/
[root@jenkins demo]# cp ../tomcat-java-demo/* ./ -rf
[root@jenkins demo]# ls
db  Dockerfile  LICENSE  pom.xml  README.md  src

提交分为三步 提交到我们的暂存区 [root@jenkins demo]# git add . 从暂存区提交到我们的本地仓库,本地也是一个仓库 [root@jenkins demo]# git commit -m 'all' 这里可能会报错

[root@jenkins tomcat-java-demo]#  git commit -m "all"

*** Please tell me who you are.

Run

  git config --global user.email "you@example.com"
  git config --global user.name "Your Name"

to set your account's default identity.
Omit --global to set the identity only in this repository.

fatal: unable to auto-detect email address (got 'root@jenkins.(none)')

解决方案:需要添加邮件和name,在.git的隐藏文件下的config文件内,添加以下配置

[root@jenkins demo]# cd .git/
[root@jenkins .git]# ls
branches  config  description  HEAD  hooks  index  info  objects  refs
[root@jenkins .git]# vim config
[user]
        name = zhaocheng
    email = 1741845455@qq.com
[root@jenkins .git]# git config user.name "zhaocheng"
这里在demo下执行,不然找不到相应指令
[root@jenkins demo]# git commit -m "all"

执行成功

推送到远程master分支里面

[root@jenkins demo]# git push origin master
git@192.168.30.22's password: 
Counting objects: 179, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (166/166), done.
Writing objects: 100% (179/179), 1.12 MiB | 0 bytes/s, done.
Total 179 (delta 4), reused 0 (delta 0)
To git@192.168.30.22:/home/git/demo.git
 * [new branch]      master -> master

**2.在所有主机安装docker ** Docker版本 社区版:CE 企业一般用 企业版:EE 一般研究docker的公司用 官方网址:https://docs.docker.com yum安装

$ sudo yum install -y yum-utils \
 device-mapper-persistent-data \
 lvm2

添加Docker软件包源

$ sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

安装Docker-ce

$ sudo yum install docker-ce
启动Docker
$ sudo systemctl start docker

二进制安装docker,离线https://download.docker.com/linux/static/stable/x86_64/ 这里也可以不用官方的docker-ce源,用阿里云的也可以,阿里的速度快一些 阿里云源:http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 建议使用daocloud的加速器 该脚本可以将 --registry-mirror 加入到你的 Docker 配置文件 /etc/docker/daemon.json 中

curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io

配置完重启docker 
$ sudo systemctl restart docker

3.部署Harbor私有仓库 下载好harbor上传我们的根目录,下载地址Harbor官方下载 https://github.com/goharbor/harbor

[root@harbor-mysql ~]# ls
harbor-offline-installer-v1.8.1.tgz

部署下载安装docker-compose Docker-compose文档地址https://docs.docker.com/compose/install/

[root@harbor-mysql ~]# curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
[root@harbor-mysql ~]# chmod +x /usr/local/bin/docker-compose
[root@harbor-mysql ~]# docker-compose --version
docker-compose version 1.24.1, build 4667896b

部署Harbor服务

[root@harbor-mysql ~]# tar xf harbor-offline-installer-v1.8.1.tgz -C /usr/local
[root@harbor-mysql ~]# cd /usr/local/harbor/
[root@harbor-mysql harbor]# ls
harbor.v1.8.1.tar.gz  harbor.yml  install.sh  LICENSE  prepare
[root@harbor-mysql harbor]# vim harbor.cfg
修改配置文件yml,修改安装的ip地址
Hostname : 192.168.30.24:80

启动并安装Harbor 配置完成后就可以启动Harbor了 [root@harbor-git harbor]# ./install.sh 访问本机

通过Dockerfile部署java镜像并推送镜像仓库

这里构建的时候需要注意版本问题,每次官方更新就会更改tomcat的版本,构建镜像的时候写dockerfile需要注意

[root@localhost Dockerfile]# vim Dockerfile-tomcat 
FROM centos:7
MAINTAINER www.xxx.com

ENV VERSION=8.5.43

RUN yum install java-1.8.0-openjdk wget curl unzip iproute net-tools -y && \
    yum clean all && \
    rm -rf /var/cache/yum/*

RUN wget http://mirror.bit.edu.cn/apache/tomcat/tomcat-8/v${VERSION}/bin/apache-tomcat-${VERSION}.tar.gz && \
    tar zxf apache-tomcat-${VERSION}.tar.gz && \
    mv apache-tomcat-${VERSION} /usr/local/tomcat && \
    rm -rf apache-tomcat-${VERSION}.tar.gz /usr/local/tomcat/webapps/* && \
    mkdir /usr/local/tomcat/webapps/test && \
    echo "ok" > /usr/local/tomcat/webapps/test/status.html && \
    sed -i '1a JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom"' /usr/local/tomcat/bin/catalina.sh && \
    ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

ENV PATH $PATH:/usr/local/tomcat/bin

WORKDIR /usr/local/tomcat

EXPOSE 8080
CMD ["catalina.sh", "run"]

[root@localhost Dockerfile]# docker build -t tomcat:v1 -f Dockerfile-tomcat .
[root@jenkins Dockerfile]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tomcat              v1                  727bd5f299ba        4 seconds ago       427MB
centos              7                   67fa590cfc1c        30 hours ago        202MB

jenkins主机配置对harbor仓库的信任,因为是http配置

[root@jenkins ~]# vim /etc/docker/daemon.json 
{
        "registry-mirrors": ["http://f1361db2.m.daocloud.io"],
        "insecure-registries": ["192.168.30.22"]
}
[root@jenkins ~]# systemctl restart docker
[root@jenkins ~]# docker login 192.168.30.22
Username: admin
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

推送tomcat镜像到我们的harbor仓库上

[root@jenkins ~]# docker tag tomcat:v1 192.168.30.22/library/tomcat:v1
[root@jenkins ~]# docker push 192.168.30.22/library/tomcat:v1

4.jenkins环境部署 去官方网站下载war包,下载tomcat和maven包和jdk https://jenkins.io/zh/

[root@jenkins ~]# ls
demo      jenkins.war      apache-maven-3.6.1-bin.tar.gz  Dockerfile   tomcat-java-demo  apache-tomcat-9.0.22.tar.gz 
[root@jenkins ~]# tar xf apache-tomcat-9.0.22.tar.gz 
[root@jenkins ~]# mv apache-tomcat-9.0.22 /usr/local/tomcat_jenkins
[root@jenkins ~]# cd /usr/local/tomcat_jenkins/

删除不用的配置

[root@jenkins tomcat_jenkins]# cd webapps/
[root@jenkins webapps]# rm -rf *
[root@jenkins webapps]# unzip /root/jenkins.war -d ROOT

解压并启动jenkins

[root@jenkins ~]# tar xf apache-maven-3.6.1-bin.tar.gz 
[root@jenkins ~]# tar xf jdk-8u191-linux-x64.tar.gz 
[root@jenkins ~]# mv jdk1.8.0_191/ /usr/local/jdk
[root@jenkins ~]# mv apache-maven-3.6.1 /usr/local/maven
[root@jenkins ~]# vim /etc/profile
JAVA_HOME=/usr/local/jdk
PATH=$PATH:$JAVA_HOME/bin:/usr/local/maven/bin
export JAVA_HOME PATH
[root@jenkins ~]# source /etc/profile
[root@jenkins ~]# java -version
openjdk version "1.8.0_161"
OpenJDK Runtime Environment (build 1.8.0_161-b14)
OpenJDK 64-Bit Server VM (build 25.161-b14, mixed mode)
[root@jenkins ~]# mvn
mvn       mvnDebug  mvnyjp   
[root@jenkins ~]# cd /usr/local/tomcat_jenkins/bin/
[root@jenkins bin]# ./startup.sh 
Using CATALINA_BASE:   /usr/local/tomcat_jenkins
Using CATALINA_HOME:   /usr/local/tomcat_jenkins
Using CATALINA_TMPDIR: /usr/local/tomcat_jenkins/temp

Using JRE_HOME:        /usr/local/jdk/bin
Using CLASSPATH:       /usr/local/tomcat_jenkins/bin/bootstrap.jar:/usr/local/tomcat_jenkins/bin/tomcat-juli.jar
Tomcat started.

访问jenkins,默认本机8080端口,登录查看我们的密码进行登录

[root@jenkins ~]# cat .jenkins/secrets/initialAdminPassword
2691cf7fb7824a2e8015b2b546319b03

5. Jenkins流水线部署

pipeline 是一套运行于jenkins上的工作流框架,将原本独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排与可视化。 创建一个pipeline类型的Job:

安装所需插件git,pipeline 6.通过流水线发布java项目 通过pipeline/jeninsfile流水线脚本,通过文本文件来描述生命周期 整个pipeline里面经过各个阶段,以最清晰的描述来形成我们最终达成的效果 安装jenkins pipeline插件 Pipeline先最简单的语法进行演示流水线的发布

构建之后查看控制台 这个脚本也可以自己生成,需要加上认证写个地址认证信息就可以了,这里的pileline是模版,我们可以拿这个模版再去修改我们的pipeline 地址就是我们这个分支,添加进去

[root@jenkins demo]# cat .git/config 
[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
[user]
	name = zhaocheng
    email = 1741845455@qq.com
[remote "origin"]
	url = git@192.168.30.22:/home/git/demo.git
	fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
	remote = origin
	merge = refs/heads/master

因为我们这里是需要认证的用户名Git和密码去认证的,拉代码和推代码都是需要写代码的 我们这里还需要添加个凭据,一般都是基于秘钥对对做认证的,也就是我们通过ssh生成 一个公钥和私钥,将公钥放到git服务器上,私钥自己拿着,用私钥去认证,这样就不用密码了,因为jenkins是自动化,不可能人工去输入密码

[root@jenkins ~]# ssh-keygen

Id_rsa是私钥,id_rsa.pub是公钥
[root@jenkins ~]# ls .ssh/
id_rsa  id_rsa.pub  known_hosts

现在我们将公钥推送到Git服务器上,拿这个秘钥来做免秘钥登录
[root@jenkins ~]# ssh-copy-id git@192.168.30.22

这样就可以免交互登录git这台服务器上了,因为我们拉代码就是使用的这个账户,只要有这个私钥就不需要输密码了

[root@jenkins ~]# cat .ssh/id_rsa
-----BEGIN RSA PRIVATE KEY-----
.......

将私钥密码保存到git上,放到下面这个位置 把我们的pipeline生成的拉取代码的信息替换成我们刚才生成的


checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '1d00c1d2-6b5a-4e53-8925-144aacdc289d', url: 'git@192.168.30.22:/home/git/demo.git']]])

参数化构建branch是一个变量名,然后传入到pipeline脚本里,pilnline调用这个变量名 交互的传入的值,默认是master分支 写一个pipeline脚本,把这个脚本传入到我们的pipeline中

[root@localhost ~]# ll pipeline.sh 
-rw-r--r--. 1 root root 1311 8月  16 14:11 pipeline.sh
[root@localhost ~]# cat pipeline.sh 
node { 
   // 拉取代码
   stage('Git Checkout') { 
        checkout([$class: 'GitSCM', branches: [[name: '${branch}']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '1d00c1d2-6b5a-4e53-8925-144aacdc289d', url: 'git@192.168.30.22:/home/git/demo.git']]])  
}
// 代码编译
   stage('Maven Build') {
        sh '''
        export JAVA_HOME=/usr/local/jdk
        /usr/local/maven/bin/mvn clean package -Dmaven.test.skip=true
        '''
   }
   // 项目打包到镜像并推送到镜像仓库
   stage('Build and Push Image') {
sh '''
REPOSITORY=192.168.30.22/library/tomcat-java-demo:${branch}
cat > Dockerfile << EOF
FROM 192.168.30.22/library/tomcat:v1
LABEL maintainer zhaocheng
RUN rm -rf /usr/local/tomcat/webapps/*
ADD target/*.war /usr/local/tomcat/webapps/ROOT.war
EOF
docker build -t $REPOSITORY .
docker login 192.168.30.22 -u admin -p Harbor12345
docker push $REPOSITORY
'''
   }
   // 部署到Docker主机
   stage('Deploy to Docker') {
        sh '''
        REPOSITORY=192.168.30.22/library/tomcat-java-demo:${branch}
        docker rm -f tomcat-java-demo |true
        docker pull $REPOSITORY
        docker container run -d --name tomcat-java-demo -p 88:8080 $REPOSITORY
        '''
   }

然后点build with parameters

可以看到多出来一个,这里就是一个人工交互的打哪个分支,为哪个分支打个镜像,然后在部署测试,一般master分支就是主分支,一般用于生产环境的,当然也有些开发分支,还有其他一些子分支,根据你的分支来选择,可以动态的可以帮你打这个 查看项目镜像已经上传到我们的harbor上

查看容器项目已经运行

[root@jenkins ~]# docker ps
CONTAINER ID        IMAGE                                           COMMAND             CREATED             STATUS              PORTS                  NAMES
b4de68438b80        192.168.30.22/library/tomcat-java-demo:master   "catalina.sh run"   4 minutes ago       Up 4 minutes        0.0.0.0:88->8080/tcp   tomcat-java-demo

访问容器暴露的端口,本机的88端口 项目完成,赶快挑一个美女回家吧!!! 优秀博主阿良博客:https://blog.51cto.com/lizhenliang