特别注意: 本文主要是来自:
Docker+Jenkins+Gitee自动化部署maven项目,加入Nexus镜像仓库(补充篇)_gitee镜像仓库-CSDN博客

Docker+Jenkins+Gitee自动化部署maven项目_docker运行maven-CSDN博客

感谢大佬的付出,我跟随大佬的步伐,实践在自己记录改动,为了自己的步骤更清晰些

自己记忆更深刻。                                                                         --- 致敬: peace and love 

有些改动是为了适配我自己的服务器腾讯云 centos7 2H2G。适量看情况各位看官

1.简介

各位看官老爷,本文为Jenkins实战,注重实际过程,阅读完会有以下收获:

  • 了解如何使用Docker安装Jenkins
  • 了解如何使用Jenkins部署maven项目
  • 了解如何使用Jenkins+Gitee实现自动化部署

2.Jenkins介绍

相信,正在读这篇文章的你,对Jenkins应该有或多或少的了解,就算没有也应该在某个地方听说过。👍

接下来,我们就一起来进行探索吧。

2.1 Jenkins是什么

Jenkins是一个开源的自动化工具,可以自动化地完成构建、测试、交付或部署等任务。总之重点就是三个字:自动化,至于如何实现这些功能,Jenkins基于插件化的机制,提供了众多的插件来完成持续集成与持续部署。

2.2 什么是持续集成与持续部署

在软件开发中经常会提到持续集成(Continuous Integration)和持续部署(Continuous Delivery),那么它们的真正意思是什么呢?

『持续集成』:当我们向代码仓库提交代码后,可以对变更进行监测,进而实现自动拉取代码、构建、测试等操作。试想一下,如果这些操作都手动进行,效率是非常低的,因而提出了持续集成。

『持续部署』:持续集成帮助我们实现了对项目的自动化构建、测试等工作,我们知道,项目最终需要部署到服务器上,在不借助Jenkins的情况下,需要我们手动将项目部署到服务器上,如果项目数量多,就会容易出现错误且效率低,而且特别麻烦,因而提出了持续部署,来实现对项目的自动化部署。

2.3 Docker 安装

yum install -y yum-utils device-mapper-persistent-data lvm2

 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

执行命令 yum list docker-ce --showduplicates | sort -r 查看系统中可用的 Docker CE 的所有版本,并按照版本号从最新到最旧的顺序排列。

yum install docker-ce-18.06.3.ce

执行命令 systemctl start docker 启动 docker,然后可执行命令 systemctl status docker 查看 docker 的状态。

若要开机启动,可执行命令 systemctl enable docker

# 启动容器 systemctl start docker

3.Docker Nexus镜像仓库

3.1拉取镜像

阿里云镜像配置:

https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors?accounttraceid=bfba3b8ce3834baca204cd2eeeaab461nmea

docker search nexus

docker pull sonatype/nexus3

3.2创建宿主机挂载目录,并设置权限

mkdir -p /mydata/docker/nexus

chown -R 755 /mydata/docker/nexus

3.3运行镜像,访问nexus

docker run -d --restart=always --name=nexus3 \
-p 8081:8081 \
-p 7070:7070 \
--privileged=true \
-e INSTALL4J_ADD_VM_PARAMS="-Xms512M -Xmx512M -XX:MaxDirectMemorySize=512M" \
-v /mydata/docker/nexus:/nexus-data \
sonatype/nexus3

访问http://IP(域名):8081/,会出现如下欢迎界面。

点击右上角登录。会提示我们去/nexus-data/admin.password中查看密码。

我们这里直接去映射的宿主机目录下查看。

cat /mydata/docker/nexus/admin.password

输入初始密码登录后,会提示设置新密码。

设置不允许匿名访问。

3.3 私服仓库配置

点击设置按钮,然后选择Repositories,可以看到默认存在了maven的仓库。

点击Create repository,进行如下配置,我们的私服仓库就搭建好了。

3.4 登录docker仓库

尝试在Jenkins服务器执行登录docker仓库的命令。

docker login -u admin -p 123456 192.168.110.101:7070

却报错了,大概意思是返回的我需要一个HTTPS,你却返回的是HTTP。

这是docker的安全机制,我们可以进行配置,让其允许客户端发送HTTP请求。

vim /etc/docker/daemon.json

修改daemon.json,并添加如下内容。

{ "insecure-registries":["192.168.110.101:7070"] }

然后重启docker。

systemctl restart docker

重新执行登录命令。如下界面表示登录成功。

记得,应用服务器也需要进行同样的操作。

4.Docker安装Jenkins

系统环境:Centos7 + Docker laster

4.1 拉取镜像

docker pull jenkins/jenkins:lts

4.2 文件夹挂载

mkdir -p /mydata/docker/jenkins

4.3 启动容器

docker run -d --restart=always --name jenkins -uroot -p 8080:8080 -p 50000:50000 \
-v /mydata/docker/jenkins:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/bin/docker:/usr/bin/docker \
jenkins/jenkins:lts

说明:这里我们挂载了宿主机的/var/run/docker.sock以及/usr/bin/docker,是因为,我们后续需要在容器内执行docker相关命令

4.4首次启动Jenkins加载很慢的解决办法

出现这个情况时,是因为Jenkins的默认更新镜像用的国外的镜像,把更新镜像改成国内的
即可。 首先进入Jenkins的安装目录
比如我是Linux系统,安装在 /mydata/docker/jenkins/下面,进入这个目录,
然后打开hudson.model.UpdateCenter.xml
这个配置文件; 将https://updates.jenkins.io/update-center.json;
修改成http://mirror.xmission.com/jenkins/updates/update-center.json;
之后重启Jenkins服务,再重新刷新Jenkins启动页面即可。

cat /mydata/docker/jenkins/hudson.model.UpdateCenter.xml

更改后的配置如下:

<?xml version='1.1' encoding='UTF-8'?>
<sites>
  <site>
    <id>default</id>
    <url>http://mirror.xmission.com/jenkins/updates/update-center.json</url>
  </site>
</sites>
-----------------
配置完后重启,再次安装就ok!

4.5 Jenkins初体验

访问http://IP(域名):8080,会出现如下界面:

提示我们可以去容器的/var/jenkins_home/secrets/initialAdminPassword中查看登录密码,我们一开始已经将/var/jenkins_home挂载到宿主机的/mydata/docker/jenkins,因此我们直接去宿主机的对应目录进行查看。

# 查看初始化登录密码

cat  /mydata/docker/jenkins/secrets/initialAdminPassword

然后将密码复制粘贴到输入框,会进入如下界面:

不得不说,这里Jenkins的选项对于新手小白还是挺友好的,我们选择安装推荐的插件,至于后面我们所要用到的功能,再去插件市场按需安装即可。

可以看到,Jenkins为我们安装了Git、Pipeline等常用插件,因为Jenkins默认使用的是国外的安装源,咱们耐心等待一下。🍨

经历过漫长的等待,终于,终于,这个步骤是走完了,但还是有些插件下载失败了,后续我们再手动安装吧。不得不说,这下载速度着实有点慢啊!!!

这里我们就不创建新用户了,使用admin账户继续。

点击保存并完成。提示部分插件需要重启才会生效。

终于,它来了。小伙伴们上号!!!

主界面如下:

这里我们先修改一下admin账户的登录密码,否则只能使用安装时提到的初始化密码。当然,如果你在前面的步骤中创建了新的管理员用户,就可以忽略该步骤。

4.6 Jenkins插件安装、环境配置

我们这里是部署一个maven的单模块项目,同时需要用到Gitee的WebHook,因此需要下载Maven、Gitee相关的插件,所以在Jenkins首页选择系统管理—》插件管理,搜索进行下载即可。

下载完成后,点击返回首页。

4.7 配置maven

在Jenkins首页点击系统管理—》全局工具配置。在这里我们可以对Maven、JDK等要使用的环境进行配置。我这里只对Maven进行了配置,JDK无需配置,因为我们后续在将项目打包成Docker镜像时,会将JRE运行环境一起打包。

在Maven配置这里,使用默认Maven配置即可。由于我们的Jenkins运行在Docker之中,因此需要在容器中安装Maven,这里我们选择自动安装(会安装到/var/jenkins_home/tools目录下),也可以自行下载,然后将文件放在该目录下即可。

4.8 Gitee插件安装

同 Maven 安装 搜索 Gitee

4.9 创建公钥和私钥 

创建 公钥 和 私钥, 公钥放在 Gitee 中,私钥放在 Jenkins 凭证中

4.9.1 公钥私钥的创建

通过 Gitee 我们能够知道 如何创建 公钥和私钥

当前windows 进入 cmd 执行下面的指令 Jenkins@work.com 为你的密钥Key

ssh-keygen -t ed25519 -C "Jenkins@work.com" 

# 生成密钥,一直按回车即可。

ssh-keygen -t ed25519 -C "jenkins@example.com"

# 查看生成的 SSH 公钥和私钥:

ls ~/.ssh/

输出: id_ed25519 id_ed25519.pub

  • 私钥文件 id_ed25519
  • 公钥文件 id_ed25519.pub

# 查看公钥

cat ~/.ssh/id_ed25519.pub

 4.9.2 Gitee 中设置 公钥

查看 id_ed25519.pub 中的信息,复制出来,放置到

添加成功之后,出现 

 4.9.3 Jenkins 添加凭据

由于需要使用Git从Gitee仓库拉取代码,我们这里添加一个Gitee的SSH key。Jenkins首页—》系统管理—》Credentials,这里应该是Jenkins的汉化插件没有汉化完全,不过无伤大雅。

添加凭据页面

将私钥添加到凭据中,一个凭据就添加好了。

5.Jenkins自动化部署Maven单模块项目

5.1 准备Maven项目

准备一个Maven项目,我这里是一个简单的基于SpringBoot的Web项目。项目结构如下:

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.7</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.stone</groupId>
    <artifactId>jenkins-test</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <description>Jenkins-test</description>

    <properties>
        <java.version>11</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.5.7</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <!--开启分层构建-->
                    <layers>
                        <enabled>true</enabled>
                    </layers>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Dockerfile

# 指定基础镜像,这是分阶段构建的前期阶段
FROM openjdk:11-jre   as builder
# 执行工作目录
WORKDIR apps
# 配置参数
ARG JAR_FILE=target/*.jar
# 将编译构建得到的jar文件复制到镜像空间中
COPY ${JAR_FILE} application.jar
# 通过工具spring-boot-jarmode-layertools从application.jar中提取拆分后的构建结果
RUN java -Djarmode=layertools -jar application.jar extract

# 正式构建镜像
FROM openjdk:11-jre
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone
WORKDIR apps
# 前一阶段从jar中提取除了多个文件,这里分别执行COPY命令复制到镜像空间中,每次COPY都是一个layer
COPY --from=builder apps/dependencies/ ./
COPY --from=builder apps/spring-boot-loader/ ./
COPY --from=builder apps/snapshot-dependencies/ ./
COPY --from=builder apps/application/ ./
ENTRYPOINT java ${JAVA_OPTS} org.springframework.boot.loader.JarLauncher

5.2 Jenkins任务配置

5.2.1 Jenkins首页点击新建任务,选择构建一个maven项目。

5.2.2 Git配置

5.2.3 Gitee的webhook配置

我这儿勾选的是当仓库有推送代码事件时触发自动构建。

配置WebHook密码。

Gitee中添加WebHook。

5.2.4 编译、打包

clean package -Dmaven.test.skip=true
5.2.5 编译、打包后执行后置脚本

我这儿准备了一个deploy.sh,并放在容器的/var/jenkins_home/sh目录下 也就是 /mydata/docker/jenkins/ 下

目录挂载了:/var/jenkins_home 需要被替换

bash /mydata/docker/jenkins/sh/deploy.sh ${JOB_NAME} master

deploy.sh

#!/bin/bash
# 服务名称
SERVER_NAME=$1
# 镜像tag
IMAGE_TAG=$2
# 镜像名称
IMAGE_NAME=$SERVER_NAME:$IMAGE_TAG
echo "------ 开始构建镜像:${SERVER_NAME} ------"
docker build -t ${IMAGE_NAME} .
echo "------ 镜像构建结束:${IMAGE_NAME} ------"
if [[ -n $(docker ps -q -f "name=^${SERVER_NAME}$") ]];then
    echo "------ 容器正在运行:${SERVER_NAME} ------"
    echo "------ 停止容器:$SERVER_NAME ------"
    docker stop $SERVER_NAME
    echo "------ 删除容器:$SERVER_NAME ------"
    docker rm $SERVER_NAME
else
    echo "------ 容器未在运行:${SERVER_NAME} ------"
    echo "------ 删除容器:$SERVER_NAME ------"
    docker rm $SERVER_NAME
fi

echo "------ 开始运行容器:$SERVER_NAME ------"
docker run -d --name $SERVER_NAME -p 9090:9090 ${IMAGE_NAME}
echo "------ 清理虚悬镜像 ------"
if [[ -n $(docker images | grep "none" | awk '{print $3}') ]];then
    docker rmi -f $(docker images | grep "none" | awk '{print $3}')
fi
#!/bin/bash
# service name 
SERVER_NAME=$1
# docker image tag
IMAGE_TAG=$2
# docker image name
IMAGE_NAME=$SERVER_NAME:$IMAGE_TAG
echo "------ create image is doing:${SERVER_NAME} ------"
docker build -t ${IMAGE_NAME} .
echo "------ create image is done:${IMAGE_NAME} ------"
if [[ -n $(docker ps -q -f "name=^${SERVER_NAME}$") ]];then
    echo "------ container is runing:${SERVER_NAME} ------"
    echo "------ stop container:$SERVER_NAME ------"
    docker stop $SERVER_NAME
    echo "------ delete container:$SERVER_NAME ------"
    docker rm $SERVER_NAME
else
    echo "------ container never run:${SERVER_NAME} ------"
    echo "------ delete container:$SERVER_NAME ------"
    docker rm $SERVER_NAME
fi
 
echo "------ start runing container:$SERVER_NAME ------"
docker run -d --name $SERVER_NAME -p 9090:9090 ${IMAGE_NAME}
echo "------ clear other xuxuan image  ------"
if [[ -n $(docker images | grep "none" | awk '{print $3}') ]];then
    docker rmi -f $(docker images | grep "none" | awk '{print $3}')
fi

可以给 deploy.sh 赋予权限 进入对应文件夹下

执行: chmod -R 777 *.sh

5.3 手动部署

点击立即构建

查看日志

拉取代码。

编译、打包。

构建镜像、运行容器。

查看运行中的容器,jenkins-maven已成功运行。

 自动部署

查看日志,拉取到最新的commit信息。

--------------------------------------------------------------------------------------------------------------------------------

 2. 实现通过 Nexus 镜像仓库部署至其他的服务器

在上文中,已经实现了 基于  Docker + Jenkins 构建了Maven 的单机项目

同时也构建了 Nexus 的私有镜像仓库,接下来我们需要通过 Jenkins 自动打包镜像,上传至

私有镜像仓库,然后给其他服务器发送指令,让其去指定仓库下载镜像,同时自动执行该镜像

不多讲,直接上去一顿操作猛如虎。。。。。。。。。

2.1 安装插件

前面我们就提到过,要在应用服务器拉取镜像并运行,这就需要我们通过远程执行脚本命令。

因此我们这儿需要在Jenkins中安装相应的插件:Publish Over SSH,可以通过它向远程服务器执行脚本,发送文件等。

2.2 配置SSH的公私钥文件

1)生成公私钥文件

在Jenkins的宿主机上执行以下命令,一直按回车即可。(Windows cmd 中执行是一样的)

ssh-keygen -t rsa

会在/root/.ssh目录下生成私钥文件id_rsa和公钥文件id_rsa.pub。 (windows 用户文件中)

2)配置私钥

然后将私钥文件id_rsa放到Jenkins容器的/var/jenkins_home/key目录下。

3)配置公钥

将公钥文件id_rsa.pub放入应用服务器的/root/.ssh目录下,并执行以下命令。

cat id_rsa.pub >> authorized_keys

 然后修改应用服务器的/etc/ssh/sshd_config

vim /etc/ssh/sshd_config

# 加入如下配置

PubkeyAuthentication yes

RSAAuthentication yes

 重启sshd服务。

systemctl restart sshd

2.3 Jenkins系统配置 

然后,我们需要去Jenkins的系统管理—》系统配置里,添加SSH Server。

第一步,配置私钥。

第二步,配置远程应用服务器信息。

2.4 Jenkins任务配置

前面的步骤可以参照【Docker+Jenkins+Gitee自动化部署maven项目】一文,我们这里会对Post Steps环节进行补充,即执行后置脚本。

执行完前面的步骤,项目已经打成jar包了,我们后面只需要进行如下配置:

构建镜像并推送到私服仓库。
向应用服务器发送脚本命令,拉取镜像并运行服务(通过Publish Over SSH)。

1)构建镜像并推送到私服仓库

bash /var/jenkins_home/sh/build.sh ${JOB_NAME} master

build.sh

#!/bin/bash
# 服务名称
SERVER_NAME=$1
# 镜像tag
IMAGE_TAG=$2
# docker仓库
DOCKER_REPOSITORY="192.168.110.101:7070"
# 镜像名称
IMAGE_NAME=${DOCKER_REPOSITORY}/$SERVER_NAME:$IMAGE_TAG
echo "------ 开始构建镜像:${SERVER_NAME} ------"
docker build -t ${IMAGE_NAME} .
# 也可以直接在Jenkins容器内直接该执行
docker login -u admin -p 123456 192.168.110.101:7070
echo "------ 开始推送镜像 ------"
docker push ${IMAGE_NAME}
 

#!/bin/bash
# service name
SERVER_NAME=$1
# image tag
IMAGE_TAG=$2
# docker ck
DOCKER_REPOSITORY="192.168.110.101:7070"
# images name
IMAGE_NAME=${DOCKER_REPOSITORY}/$SERVER_NAME:$IMAGE_TAG
echo "------ start create ${SERVER_NAME} ------"
docker build -t ${IMAGE_NAME} .
docker login -u admin -p 123456 192.168.110.101:7070
echo "------ start push image ------"
docker push ${IMAGE_NAME} 

 2)向应用服务器发送脚本命令,拉取镜像并运行服务。

deploy.sh

# docker仓库
DOCKER_REPOSITORY="192.168.110.101:7070"
SERVER_NAME=$1
IMAGE_TAG=$2
IMAGE_NAME=${DOCKER_REPOSITORY}/${SERVER_NAME}:${IMAGE_TAG}
docker pull ${IMAGE_NAME}
if [[ -n $(docker ps -q -f "name=^${SERVER_NAME}$") ]];then
    echo "------ 容器正在运行:${SERVER_NAME} ------"
    echo "------ 停止容器:$SERVER_NAME ------"
    docker stop $SERVER_NAME
    echo "------ 删除容器:$SERVER_NAME ------"
    docker rm $SERVER_NAME
else
    echo "------ 容器未在运行:${SERVER_NAME} ------"
    echo "------ 删除容器:$SERVER_NAME ------"
    docker rm $SERVER_NAME
fi

echo "------ 开始运行容器:$SERVER_NAME ------"
docker run -d --name $SERVER_NAME -p 9090:9090 ${IMAGE_NAME}
echo "------ 清理虚悬镜像 ------"
if [[ -n $(docker images | grep "none" | awk '{print $3}') ]];then
    docker rmi -f $(docker images | grep "none" | awk '{print $3}')
fi

这里需要给脚本添加可执行的权限。

chmod +x /home/docker/jenkins/sh/deploy.sh

3)手动部署

这时,我们来构建一个任务试试,查看日志。

可以看到,正在向私服镜像仓库推送镜像,推送完成后,镜像仓库里也存在了。

远程脚本也执行成功,我们去看看应用服务器上的应用容器是否运行成功。

如上图所示,No Problem,应用成功运行。 

Logo

一站式 AI 云服务平台

更多推荐