企业级devops自动化部署学习 (5)jenkins构建镜像并上传到harbor仓库,生产服务器从harbor仓库拉取镜像部署应用

前置准备:Jenkins服务器(192.168.80.134),Docker仓库服务器(192.168.80.135),生产应用部署服务器(192.168.80.136)都安装docker

docker的安装:

https://www.cnblogs.com/lrc123/p/16095016.html

 

Jenkins拉取代码->编译打包->生成镜像过程

在项目pom.xml中添加dockerfile插件

<plugin>
                <groupId>com.spotify</groupId>
                <artifactId>dockerfile-maven-plugin</artifactId>
                <version>1.4.7</version>
                <configuration>
                    <repository>${project.artifactId}</repository>
                    <buildArgs>
                        <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
                    </buildArgs>
                </configuration>
            </plugin>

 

项目根路径下编写dockerfile

FROM openjdk:8-jdk-alpine
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
EXPOSE 8081
ENTRYPOINT ["java","-jar","/app.jar"]

文本说明:

from :定义了起始镜像

arg:定义了项目打包后生成的FILE参数,此参数与上面pom.xml的<JAR_FILE>对应

COPY:将项目打包好的JAR文件拷贝到当前工作目录下的app.jar

EXPOSE:暴露8081端口

ENTRYPOINT:相当于执行:java -jar app.jar启动项目

 

 

Jenkinsfile中添加构建docker镜像步骤

stage('打包docker镜像') {
            steps{
                sh 'mvn clean package dockerfile:build'
            }
         }

 

提交代码到gitlab远程仓库,并构建项目

 

 

构建发现在执行docker build的时候发现报错了:

 

添加权限:

chmod 777 /var/run/docker.sock

 

再进行构建:

 

到jenkins服务器查看镜像:docker images

镜像成功下载到了jenkins服务器。

下面我们运行镜像进行项目访问:

docker run -d -p 8081:8081 gitlab_test_demo

 

访问项目发现拒绝请求连接了,原因是因为,我当前机器开了防火墙,但是没有开放8081端口

 

开放8081端口后再访问项目:

firewall-cmd --zone=public --add-port=8081/tcp --permanent
firewall-cmd --reload

发现还是拒绝了请求,我猜想是我的springboot项目内置的tomcat服务器是8080端口,所以docker容器启动应用时也是8080端口,我们做的是8081端口映射,所以存在问题,问题解决:将项目的默认端口改成8081

 

再上传到gitlab重新构建访问:

成功访问到

 

 

镜像推送到Harbor->生产服务器拉取镜像部署项目过程

Harbor简介

Harbor(港口,港湾)是一个用于存储和分发Docker镜像的企业级Registry服务器。除了Harbor这个私有镜像仓库之外,还有Docker官方提供的Registry。相对Registry,Harbor具有很多优势:
1. 提供分层传输机制,优化网络传输 Docker镜像是是分层的,而如果每次传输都使用全量文件(所以用FTP的方式并不适合),显然不经济。必须提供识别分层传输的机制,以层的UUID为标识,确定传输的对象。

2. 提供WEB界面,优化用户体验 只用镜像的名字来进行上传下载显然很不方便,需要有一个用户界面可以支持登陆、搜索功能,包括区分公有、私有镜像。

3. 支持水平扩展集群 当有用户对镜像的上传下载操作集中在某服务器,需要对相应的访问压力作分解。

4. 良好的安全机制 企业中的开发团队有很多不同的职位,对于不同的职位人员,分配不同的权限,
具有更好的安全性。 

 

Harbor安装 

此处我的Harhor安装到另一台服务器192.168.80.135上

1、首先安装好docker并启动

2、安装docker-compose

curl -L https://github.com/docker/compose/releases/download/1.20.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

3、给docker-compose添加执行权限

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

4、查看docker-compose是否安装成功

docker-compose -version

5、进入到/opt目录下下载harbor压缩包

cd /opt
wget https://github.com/goharbor/harbor/releases/download/v2.5.0/harbor-offline-installer-v2.5.0.tgz

6、解压harbor

tar -zxvf harbor-offline-installer-v2.5.0.tgz

7、修改harbor配置(修改hostname和port,注释ssl权限认证)

cd /opt/harbor/
vim harbor.yml.tmpl

修改完后将harbor.yml.tmpl改成harbor.yml

mv harbor.yml.tmpl harbor.yml

8、安装harbor

./prepare
./install.sh

 

安装成功

 

 

Harbor的基本使用

1、harbor的相关命令

docker-compose up -d 启动
docker-compose stop 停止
docker-compose restart 重新启动

2、登录harbor

访问地址:http://192.168.80.135:85/

默认的账号密码:admin/Harbor12345

 

3、创建用户和项目

 

 

4、给项目分配用户

这里的角色权限说明

角色 权限说明
项目管理员 拥有读写操作,同时拥有用户管理/镜像扫描等管理权限
维护人员 对于指定项目拥有读写权限,创建 Webhooks 
开发者 对于指定项目拥有读写权限
访客 对于指定项目拥有只读权限
受限访客 只可以拉取项目,其他项目资源文件如log没有读权限

 

 

 

5、用刚创建的用户登录harbor

 

 

 

jenkins服务器把镜像上传到harbor

1、为已存在镜像打标签

docker tag gitlab_test_demo 192.168.80.135:85/harbor_project01/gitlab_test_demo:v1

2、推送镜像

docker push 192.168.80.135:85/harbor_project/gitlab_test_demo:v1

这条命令出现以上报错,是因为Docker没有把Harbor加入信任列表中 ,下面把Harbor地址加入到docker信任列表

vim /etc/docker/daemon.json

重启docker

systemctl daemon-reload
systemctl restart docker

#如果重启docker失败,可以将daemon.json改成daemon.conf文件
mv /etc/docker/daemon.json /etc/docker/daemon.conf

 

再次推送还是出现一样的情况:

此时猜想docker.service文件并没有读取到我们daemon.json的配置,下面继续配置docker.service文件

vim /usr/lib/systemd/system/docker.service

再次重启docker推送镜像

又出现了新的认证错误,此时需要先登录到harbor,再推送镜像

#格式:docker login -u 用户名 -p 密码 ip地址:端口
docker login -u admin -p Harbor12345 192.168.80.135:85

 

再推送镜像

千辛万苦终于推送成功了,到harbor查看:

 

 

 

生产应用部署服务器(192.168.80.136)从Harbor下载镜像

接下来,在新的服务器(192.168.80.136)模拟生产配置的服务器,从Harbor服务器拉取镜像进行项目部署

1、安装docker并启动

2、修改docker配置

vim /usr/lib/systemd/system/docker.service

--insecure-registry 192.168.80.135:85
vi /etc/docker/daemon.json
{
"registry-mirrors": ["https://zydiol88.mirror.aliyuncs.com"],
"insecure-registries": ["192.168.80.135:85"]
}

重启docker

systemctl daemon-reload
systemctl restart docker

#如果重启docker失败,可以将daemon.json改成daemon.conf文件
mv /etc/docker/daemon.json /etc/docker/daemon.conf

 

 

3、登录harbor,并下载并镜像

docker login -u admin -p Harbor12345 192.168.80.135:85
docker pull 192.168.80.135:85/harbor_project01/gitlab_test_demo:v1

 

 

 

 

实际项目部署:jenkins拉取gitlab代码->jenkins中编译打包,生成镜像上传到harbor仓库->生产应用服务器(192.168.80.136)拉取镜像部署

1、jenkins添加harbor凭证

2、创建后,拿出自动生成的id,后边把id配置到项目的Jenkinsfile中

3、jenkins中添加一个project_name环境变量参数,后边如果我们项目添加了,可以通过选择环境变量${project_name}做不同项目的构建

 

4、使用片段生成器生成替代harbor明文登录信息

5、编写jenkinsfile脚本

pipeline {
    environment{
        //声明gitlab的凭证
        gitlab_auth="4331acf3-f1e0-4e5a-a3c7-b4df55a286c6"
        //gitlab项目url
        gitlab_url="git@192.168.80.133:test_group01/gitlab_test_demo.git"
        //harbor地址
        harbor_url="192.168.80.135:85"
        //定义镜像标签
        tag="latest"
        //定义harbor项目名称
        harbor_project="harbor_project01"
        //定义harbor凭证
        harbor_auth="19ceff97-64ad-49f7-b51d-d06661787aaa"

    }
     agent any



    stages {
        stage('从gitlab中拉取代码') {
            steps {
               checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], extensions: [], userRemoteConfigs: [[credentialsId: "${gitlab_auth}", url: "${gitlab_url}"]]])
            }
        }

         stage('编译打包并构建docker镜像') {
            steps{
                sh "mvn  clean package dockerfile:build"
            }
         }

         stage('镜像打标签并上传镜像') {
            environment{
                //定义镜像名称
                  imageName="${project_name}:${tag}"

            }

            steps{
                //打标签
                sh "docker tag ${imageName} ${harbor_url}/${harbor_project}/${imageName}"
                //镜像推送到harbor
                withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: "password", usernameVariable: "username")]) {
                    //登录到harbor
                    sh "docker login -u ${username} -p ${password} ${harbor_url}"
                    //镜像上传
                    sh "docker push ${harbor_url}/${harbor_project}/${imageName}"

                }
            }
         }


    }

    post {
        always {
            emailext(
                subject: '构建通知:${PROJECT_NAME} - Build # ${BUILD_NUMBER} -${BUILD_STATUS}!',
                body: '${FILE,path="email.html"}',
                to: '11234512@qq.com'
            )
        }
    }
}

 

6、构建项目

从控制台可以看到镜像推送成功,到harbor仓库查看

 

 

 

7、生产应用服务器拉取镜像并发布服务

(1)jenkins安装publish over ssh插件

我们需要在jenkins服务器(192.168.80.134)中调用远程的生产服务器(192.168.80.136)中拉取镜像并部署,此时需要先安装publish over ssh插件,可以实现远程发送shell命令

 

(2)在jenkins服务器(192.168.80.134)中拷贝公钥到远程生产服务器(192.168.80.136)中

ssh-copy-id 192.168.80.136

到生产服务器(192.168.80.136)中查看:

(3)在jenkins配置添加远程ssh

(3.1)在configure system的publish over ssh中填入私钥

私钥获取:

cat /root/.ssh/id_rsa

 

(3.2)配置ssh server

(3.3)测试连接

 

 

(4)在生产服务器编写一个shell脚本,完成项目的部署操作

(4.1)创建/opt/jenkins_shell目录,并进入到该目录
mkdir /opt/jenkins_shell
cd /opt/jenkins_shell
(4.2)创建文件deploy.sh,编写部署脚本
touch deploy.sh
vim deploy.sh

脚本如下:

#! /bin/sh
#接收外部参数
harbor_url=$1
harbor_project=$2
project_name=$3
tag=$4
port=$5

imageName=$harbor_url/$harbor_project/$project_name:$tag

echo "$imageName"

#查询容器是否存在,存在则删除
containerId=`docker ps -a | grep -w ${project_name}:${tag}  | awk '{print $1}'`
if [ "$containerId" !=  "" ] ; then
    #停掉容器
    docker stop $containerId

    #删除容器
    docker rm $containerId
        
        echo "成功删除容器"
fi

#查询镜像是否存在,存在则删除
imageId=`docker images | grep -w $project_name  | awk '{print $3}'`

if [ "$imageId" !=  "" ] ; then
      
    #删除镜像
    docker rmi -f $imageId
        
        echo "成功删除镜像"
fi

# 登录Harbor
docker login -u admin -p Harbor12345 $harbor_url

# 下载镜像
docker pull $imageName

# 启动容器
docker run -di -p $port:$port $imageName

echo "容器启动成功"
(4.3)给deploy.sh脚本添加可执行权限
chmod +x deploy.sh

 

(5)在jenkins添加一个port参数,参数化项目暴露的端口

 

(6)修改Jenkinsfile

 

pipeline {
    environment{
        //声明gitlab的凭证
        gitlab_auth="4331acf3-f1e0-4e5a-a3c7-b4df55a286c6"
        //gitlab项目url
        gitlab_url="git@192.168.80.133:test_group01/gitlab_test_demo.git"
        //harbor地址
        harbor_url="192.168.80.135:85"
        //定义镜像标签
        tag="latest"
        //定义harbor项目名称
        harbor_project="harbor_project01"
        //定义harbor凭证
        harbor_auth="19ceff97-64ad-49f7-b51d-d06661787aaa"

    }
     agent any



    stages {
        stage('从gitlab中拉取代码') {
            steps {
               checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], extensions: [], userRemoteConfigs: [[credentialsId: "${gitlab_auth}", url: "${gitlab_url}"]]])
            }
        }

         stage('编译打包并构建docker镜像') {
            steps{
                sh "mvn  clean package dockerfile:build"
            }
         }

         stage('镜像打标签并上传镜像') {
            environment{
                //定义镜像名称
                  imageName="${project_name}:${tag}"

            }

            steps{
                //打标签
                sh "docker tag ${imageName} ${harbor_url}/${harbor_project}/${imageName}"
                //镜像推送到harbor
                withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: "password", usernameVariable: "username")]) {
                    //登录到harbor
                    sh "docker login -u ${username} -p ${password} ${harbor_url}"
                    //镜像上传
                    sh "docker push ${harbor_url}/${harbor_project}/${imageName}"
                }
                //删除本地镜像
                sh "docker rmi -f ${imageName}"
                sh "docker rmi -f ${harbor_url}/${harbor_project}/${imageName}"
            }
         }

           stage('远程部署应用'){
                 steps{
                         sshPublisher(publishers: [sshPublisherDesc(configName: 'product_server',transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand:"/opt/jenkins_shell/deploy.sh $harbor_url $harbor_project $project_name $tag $port", execTimeout: 120000, flatten: false, makeEmptyDirs: false,
                         noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '',remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')],usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])

                     }


                   }


    }

    post {
        always {
            emailext(
                subject: '构建通知:${PROJECT_NAME} - Build # ${BUILD_NUMBER} -${BUILD_STATUS}!',
                body: '${FILE,path="email.html"}',
                to: '11234512@qq.com'
            )
        }
    }
}

 

(7)构建执行

控制台看到部署成功了,此时我们在生产服务器访问项目:192.168.80.136:8081/hello

自此,一整套的自动化部署流程已经完成,回顾流程示意图:

posted @ 2022-07-10 19:09  筱筱创  阅读(2599)  评论(0编辑  收藏  举报