一、Jenkins配置
进入 Jenkins 页面,点击左侧的 Manage Jenkins 进行配置
1. 工具配置
在 Jenkins 的配置管理页面,选择 Tool ,进入工具配置管理页面
在工具配置管理页面可以配置 Java, Maven, Git 等工具
配置 Java
进入 Java清华镜像,选择 Java 版本,复制对应下载的 URL,进入宿主机的目录,执行命令
# 下载 OpenJDK21
$ wget https://mirrors.tuna.tsinghua.edu.cn/Adoptium/21/jdk/x64/linux/OpenJDK21U-jdk_x64_linux_hotspot_21.0.5_11.tar.gz
将下载好的文件移动到 Jenkins 挂载目录中,这里用的是 1Panel 进行挂载
# 将下载的压缩包复制到 Jenkins 容器挂载的目录中
$ mv OpenJDK21U-jdk_x64_linux_hotspot_21.0.5_11.tar.gz /opt/1panel/apps/jenkins/jenkins/data/openjd21.tar.gz
进入 Jenkins 容器内部,移动并解压压缩包
# 宿主机进入 Jenkins 容器
$ sudo docker exec -it 1panel_jenkins bash
# 进入挂载目录拿到压缩包并解压
$ cd /var/jenkins_home
$ mv openjdk21.tar.gz /opt/java/
# 将压缩包解压
$ cd /opt/java
$ tar -xvf openjdk21.tar.gz
# 重命名解压目录
$ mv jdk21xxx/ openjdk21/
在 Jenkins 页面中点击 JDK安装,新增JDK配置,输入名称和路径
配置 Maven
进入 Maven清华镜像源,选择 Maven 版本(这里是Maven-3,可以切换目录选择Maven2或Maven4),复制对应的下载URL,进入宿主机,执行下载命令
# 下载 apache-maven-3.9.9
$ wget https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.tar.gz
将下载好的文件同样移动到 Jenkins 容器的挂载目录中
# 移动文件至Jenkins挂载目录
$ mv apache-maven-3.9.9-bin.tar.gz /opt/1panel/apps/jenkins/jenkins/data/apache-maven-3.9.9.tar.gz
进入 Jenkins 容器,移动并解压下载包
# 宿主机进入 Jenkins 容器
$ sudo docker exec -it 1panel_jenkins bash
# 进入 Jenkins 挂载目录,移动压缩包
$ cd /var/jenkins_home
$ mv apache-maven-3.9.9.tar.gz /opt/maven
# 将压缩包解压
$ mv /opt/maven
$ tar -xvf apache-maven-3.9.9.tar.gz
在 Jenkins 页面拖动到尾部,选择 Maven 安装,并取消勾选自动安装,输入名称和工作目录
2. 凭据配置
进入 Jenkins 配置管理页面,选择 凭据管理
在凭据管理页面,选择列表中域下方的 全局
在全局凭据页面点击右上方的 Add Credentials 添加凭据
配置 Github SSH 私钥
进入jenkins容器,使用 cd ~ 命令进入工作目录,随后使用 ssh-keygen 生成公钥和私钥
# 宿主机进入 docker 容器
$ sudo docker exec -it 1panel_jenkins bash
# 进入容器工作目录,生成 ssh-keygen
root@aed76f497e0a:/# cd ~
root@aed76f497e0a:~# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): # 这里要求输入ssh目录, 使用默认直接回车即可
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase): # 这里同样要求输入私钥密文, 默认为空直接回车即可
Enter same passphrase again: # 再次输入私钥密文, 和上面一样直接回车
Your identification has been saved in /root/.ssh/id_rsa
Your public key has been saved in /root/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:cWqus7d9DV3W6cP0v8kGABKJslR/xZvlZgF/EK8f7eg root@aed76f497e0a
The key's randomart image is:
+---[RSA 3072]----+
| ....o .o.o. |
| o ..o ....oo |
| . o .o.o =..oo|
| . .+ + +oo=|
| S +o++o|
| o ..o*o|
| . oo.+|
| .... ..o.o|
| o+.... E+.|
+----[SHA256]-----+
登录到 Github 页面,点击头像,出现侧边栏,选择 Settings 进入设置页面,在设置页面选择 SSH and GPG keys ,点击 New SSH key 添加刚才创建的 ssh Key
在 docker 容器内部进入 .ssh 目录,查看刚才生成的公钥
root@aed76f497e0a:~# cd .ssh/
root@aed76f497e0a:~/.ssh# ls
id_rsa id_rsa.pub
root@aed76f497e0a:~/.ssh# cat id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC41sC+SUEcwaHM9JoLYWcFNd4CrYBMcmtEyUCCbO26wbd6j56ZQdZ5x5rHUN7Att5ZZeaS3YQSOT5ApXEaqLXOmXpiXU7E+qA9UaKS/X4zRj81ipnSdOsAokqC+tqey+mVGy77sVvl6g78v+dUe6CREzT8wS5OYrabPHuZ4tZYBVcA538cWr67ALn+7F5eGVkuTzirdwucWVCk50BYb+ME6gwbRviFO4OOUW29njbiPuQr427XcYy9DslLXTwkwGRU+X6vJ2Us+mRchyTz32VaIIrR1M5EjMKs54mKE50voCok2oH07zvUGopMS8L25GfetOmMGYKZdD08GDafIkNhPXtZg+1vKOo0UxqIqU10b3FQ58w8UdLBrsX3iYaUnAdhlRAZdPYjCAtw5nWiKliG3Al9fW7dqbl2Q8Ox2OzW2NiUahSWDHDs73yJZR2H/LuxnnzOmumH0Hmdu+tTtKn+6mQk2PEByIZUkt9Z3Fig6VJgyePYknp2oAiMqn+qKxE= root@aed76f497e0a
将公钥内容复制到复制到 Key 内容框下,创建公钥
然后打开 Jenkins 的系统管理页面,在凭据添加页面中,选择类型为 SSH Username with Private Key 添加 SSH 私钥凭据
输入凭据的 ID,描述,Username
在私钥处选择 Enter Directly,Key点击 添加 输入私钥,这里私钥使用的是宿主机登录 Girthub 使用的私钥
# 查看 ~/.ssh 目录下私钥
root@aed76f497e0a:~/.ssh# cat id_rsa
# 以下全为私钥内容
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----
将私钥内容复制到剪贴板,并粘贴到页面上;Passphrase可置空,点击Create添加私钥
配置 Github App Key
首先进入Github页面,点击 Settings 进入账户设置页面,并在左下角选择 Developer settings 开发者选项
进入开发者选项页面后,选择 Personal access token 创建个人账户访问 Token,并选择 classic
在 Access Token 的访问范围内,勾选 repo 和 repo_hook,点击确认生成
生成后图中的部分即为 access_token,将其复制
进入 Jenkins 的配置页面,分别输入用户名和密码。
用户名输入 Github 登录账户,密码输入上方刚生成的 access_token
点击 Create 创建该凭据
3. 远程发布配置
安装 ssh Publisher 插件
在 Jenkins 系统管理页面,选择 插件管理
在插件管理页面点击左侧的 Avaiable Plugin 并搜索 Publish Over SSH 插件,这里已经安装
配置发布到的远程主机
在 Jenkins 系统管理页面选择 系统配置
向下翻阅,找到 Publish over SSH 这个配置项,选择在 Path to Key 输入 SSH 私钥路径,或者在 Key 处输入私钥内容
继续向下拖动,找到 SSH Servers 这个配置项,点击新增添加一个配置,分别输入名称,主机名,用户名,远程目录。最后可以点击右下方的 Test Configuration 来测试该配置是否生效
创建远程用户
在上面配置了发布到的远程主机,这一步我们将创建远程用户
一般来说 Jenkins 容器和发布运行的容器不在同一台服务器上,不过本文中只有一台云主机,因此流程是
Jenkins 容器 --远程发布--> Host主机 ----> docker-compose 部署
这一步也可以使用当前的主机用户,如 root, ubuntu 等等,不过这里为了隔离,选择创建一个新的用户
# 切换为 root 用户
$ su
# 创建用户
root:/# useradd -s /bin/bash -m jenkins
# 修改新用户密码
root:/# passwd
New password: # 输入密码
Retype new password: # 二次输入
passwd: password updated successfully
接下来需要修改 sshd_config 文件,允许新用户通过密码和SSH登录,默认路径为 /etc/ssh/sshd_config
# 允许用户通过密码登录, 因为传输公钥需要输入密码
PasswordAuthentication yes
# 允许使用 ssh 登录的用户, 如果为 * 则不需要改动, 否则需要在末尾加入新用户
AllowUsers root jenkins
此外,由于 docker 的权限在 root 用户手中,因此其他用户使用 docker 命令时必须使用 sudo 输入密码提升权限,然而脚本执行过程中不能够输入密码,因此还需要修改 /etc/sudoers 文件,允许该用户无需密码执行 docker 命令
修改suoders文件,添加一行
jenkins ALL=(ALL) NOPASSWD: /usr/bin/docker, /var/run/docker.sock, /usr/local/bin/docker-compose
将公钥添加到远程用户
接下来在容器内部,通过 ssh-copy-id 命令将自己的公钥添加到远程用户,随后使用 ssh 进行登录
# 使用 ssh-copy-id 复制公钥到远程用户
root@aed76f497e0a:~# ssh-copy-id -i ~/.ssh/id_rsa.pub jenkins@172.18.0.1
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
# 这里输入远程用户的密码
jenkins@172.18.0.1's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'jenkins@172.18.0.1'"
and check to make sure that only the key(s) you wanted were added.
# 使用 ssh 连接到远程用户
root@aed76f497e0a:~# ssh jenkins@172.18.0.1
System information as of Fri Nov 1 09:41:07 AM CST 2024
System load: 0.09 Processes: 182
Usage of /: 31.4% of 58.76GB Users logged in: 1
Memory usage: 54% IPv4 address for eth0: 172.16.0.3
Swap usage: 0%
=> There is 1 zombie process.
Welcome to JDCLOUD Elastic Compute Service
Last login: Thu Oct 31 15:34:45 2024 from xxx.xxx.xxx.xxx
jenkins@xxx-xxxx:~$
二、创建流水线
1. 基础配置
进入 Jenkins 面板,点击左侧的 新建 Item
在任务类型列表中选择 Pipeline(流水线)
1.1 配置 Github 地址
在流水线配置中勾选Github项目,并输入项目的URL
1.2 配置构建参
在配置中,勾选参数化构建过程,这个允许每次构建时用户输入指定参数,并支持默认值
这里配置一个参数 JAR_VERSION,因为我们打出来的包会携带版本号,所以在这里设置一个 JAR_VERSION 参数方便更换
1.3 配置 Github WebHook
下方的触发器根据个人情况勾选,这里选择了 WebHook
2. 流水线脚本
接下来需要编写流水线脚本,可以点击下方的 流水线语法 辅助编写
这里逐步给出一个完整的 pipeline
2.1 流水线框架
pipeline 的整个流程大致框架如下
pipeline {
// 声明任务可以在哪种节点上运行
agent any
// 声明需要使用的工具, 运行时会将这些工具的路径添加到 PATH 中,也可以在具体的stage中声明
tools { ... }
// 声明运行时环境变量
environment { ... }
// 声明整个流水线不同阶段
stages {
// 声明一个阶段
stage('Checkout') {
// 声明阶段中的步骤
steps {
// 具体步骤
sh 'echo Hello,World'
}
}
}
}
2.2 声明运行时环境变量
在 pipeline 脚本中,在顶层声明运行时环境变量
pipeline {
...
// 声明运行时环境变量
environment {
// 声明项目名称
PROJECT_NAME = "test-hook"
// 声明 JAR 包名称, ${JAR_VERSION} 为流水线的参数化变量
JAR_NAME = "test-hook-${JAR_VERSION}.jar"
}
}
2.3 拉取 Git 代码
接下来进入 Stage 阶段,第一步拉取 Github 代码,点击 流水线语法 进入流水线生成页面
示例步骤的类型选择 git: Git ,输入仓库的URL和分支,并选择凭据 如果URL是https类型,则选择上述配置的 Github App Key,类型为 Username and Password
上述有报错是因为 TLS handshake 不稳定,因此一般推荐使用 ssh,URL为 git@github.com:xxx 的形式
如果出现上述报错,说明 git 还没有 known_host 等信息,此时只需在容器内手动 git clone 一下即可
root@aed76f497e0a:~# git clone git@github.com:<USER_NAME>/test-hook.git
Cloning into 'test-hook'...
The authenticity of host 'github.com (20.205.243.166)' can't be established.
ED25519 key fingerprint is SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes # 这里输入 yes
Warning: Permanently added 'github.com' (ED25519) to the list of known hosts.
remote: Enumerating objects: 33, done.
remote: Counting objects: 100% (33/33), done.
remote: Compressing objects: 100% (19/19), done.
remote: Total 33 (delta 10), reused 26 (delta 6), pack-reused 0 (from 0)
Receiving objects: 100% (33/33), 4.47 KiB | 508.00 KiB/s, done.
Resolving deltas: 100% (10/10), done.
root@aed76f497e0a:~#
此时重新选择凭据则不会出现问题,点击生成流水线脚本,即可生成 git 拉取的脚本
此时将生成的内容复制,回到流水线脚本,继续编写
pipeline {
...
stages {
stage('Checkout') {
steps {
// 1. 从 Github 拉取代码
git branch: 'main', credentialsId: 'jenkins-github-host-private-key', url: 'git@github.com:<USER_NAME>/test-hook.git'
}
}
}
}
2.4 Maven编译打包
在 Git 拉取项目之后,接下来使用 maven 进行打包,不过在这一步首先需要声明 Java 和 Maven 这两个工具,否则运行时会报错找不到环境变量
点击 流水线语法 进入模板界面,在示例步骤中选择 tool: ,并选择具体的 tool,最后点击 生成流水线脚本 生成对应的语句
使用这种方式声明jdk和maven工具,git工具看情况声明
pipeline {
...
stages {
...
stage('Compile-Package') {
tools {
jdk 'OpenJDK21'
maven 'apache-maven-3.9.9'
}
}
}
}
声明完工具后就可以进行编译打包工作了
stage('Compile-Package') {
tools { ... }
steps {
sh 'mvn -Dmaven.test.failure.ignore=true clean package'
}
}
在这里声明一个 post 区域,如果打包成功,会在当前工作目录生成 target 文件夹,里面存储打包好的 JAR 包
我们需要准备 docker 部署所需要的相关文件,有以下几个:
-
docker-compose.yaml:编排模板,使用占位符配合.env文件方便修改
networks: 1panel-network: external: true services: java: command: bash /app/run.sh # 容器名称 container_name: ${CONTAINER_NAME} # 使用的 Java 版本 image: bitnami/java:${JAVA_VERSION} labels: createdBy: Apps networks: - 1panel-network ports: # 暴露对外访问IP:主机使用端口:容器内部使用端口 - ${HOST_IP}:${APP_HOST_PORT}:${APP_CONTAINER_PORT} restart: no volumes: # 可执行文件所在的目录 - ${RUNNABLE_DIR}:/app/ - ./run.sh:/app/run.sh - ./.env:/app/.env working_dir: /app -
.env:提供 docker-compose.yaml 使用的环境变量,方便修改
CODE_DIR="/opt/1panel/apps/jenkins/jenkins/data/runtime/java/" CONTAINER_NAME="test-hook-app" EXEC_SCRIPT="java -jar test-hook-1.0.jar" HOST_IP="0.0.0.0" JAVA_APP_PORT=8080 JAVA_VERSION=21 PANEL_APP_PORT_HTTP=18664 -
run.sh:容器内执行脚本,用于运行 Java 应用
#!/bin/bash source /app/.env eval $EXEC_SCRIPT
可以看到上面这三个文件中, docker-compose.yaml 和 run.sh 基本不用变动,只需要更改 .env 文件即可,因此该阶段就是生成对应的 .env 文件,这里使用了 env-setup.sh bash脚本来生成
#!/bin/bash
# 运行目录
RUNNABLE_DIR=""
# 容器名称
CONTAINER_NAME=""
# 执行脚本
EXEC_SCRIPT=""
# 主机IP(默认对外访问)
HOST_IP="0.0.0.0"
# 应用主机端口
APP_HOST_PORT=0
# 应用容器端口
APP_CONTAINER_PORT=0
# JAVA版本
JAVA_VERSION=0
function help() {
echo "Usage: env-setup.sh [OPTION]
-d, --run-dir
指定可执行文件在主机的位置
-n, --con-name
指定容器名称
-e, --exec-script
指定容器运行脚本
-i, --host-ip
指定容器对外允许的IP (默认为 0.0.0.0)
-p, --host-port
指定主机占用端口
-q, --con-port
指定容器内部端口
-v, --java-version
指定使用的JDK版本"
}
function verifyVariables() {
# 判断参数
local errors=() # 用于收集错误信息
[ -z "$RUNNABLE_DIR" ] && errors+=("run-dir unset")
[ -z "$CONTAINER_NAME" ] && errors+=("con-name unset")
[ -z "$EXEC_SCRIPT" ] && errors+=("exec-script unset")
[ "$APP_HOST_PORT" -le 0 ] && errors+=("host-port invalid")
[ "$APP_CONTAINER_PORT" -le 0 ] && errors+=("con-port invalid")
[ "$JAVA_VERSION" -le 0 ] && errors+=("java-version unset")
# 如果有错误,则输出并返回非零状态
if [ ${#errors[@]} -ne 0 ]; then
printf "%s\n" "${errors[@]}"
printf "%s\n" "$(help)"
return 1
fi
return 0 # 所有检查通过
}
function printVariables() {
file="$1"
echo -n "" > "$file"
# 这里输出时对于字符串文本, 需要手动加上单引号, 否则解析时可能报错
{
echo "RUNNABLE_DIR='$RUNNABLE_DIR'"
echo "CONTAINER_NAME='$CONTAINER_NAME'"
echo "EXEC_SCRIPT='$EXEC_SCRIPT'"
echo "HOST_IP='$HOST_IP'"
echo "APP_HOST_PORT=$APP_HOST_PORT"
echo "APP_CONTAINER_PORT=$APP_CONTAINER_PORT"
echo "JAVA_VERSION=$JAVA_VERSION"
} >> "$file"
}
parameters=$(getopt -o d:n:e:i:p:q:v: \
-l run-dir:,con-name:,exec-script:,host-ip:,host-port:,con-port:,java-version: \
-n "$0" -- "$@")
if [ $? != 0 ]; then
echo "parse parameters failed, terminating...";
exit 1;
fi
# 将$parameters设置为位置参数
eval set -- "$parameters"
# 循环解析位置参数
while true ; do
case "$1" in
-d|--run-dir) RUNNABLE_DIR="$2"; shift 2;;
-n|--con-name) CONTAINER_NAME="$2"; shift 2;;
-e|--exec-script) EXEC_SCRIPT="$2"; shift 2;;
-i|--host-ip) HOST_IP="$2"; shift 2;;
-p|--host-port) APP_HOST_PORT="$2"; shift 2;;
-q|--con-port) APP_CONTAINER_PORT="$2"; shift 2;;
-v|--java-version) JAVA_VERSION="$2"; shift 2;;
--) shift; break;;
*) echo -e "invalid option\n$(help)";exit 1;;
esac
done
# 校验参数
verifyVariables
if [ $? != 0 ]; then
exit 1;
fi
printVariables ".env"
在使用这个脚本时,只需要指定相关参数即可,如:
$ bash ./env-setup.sh \
--run-dir="./" \
--con-name=test-hook \
--exec-script="java -jar test-hook-1.0.jar" \
--host-port=8192 --con-port=8080 --java-version=21
至此容器部署所需要的工具已全部具备,这些工具全部放在 ${JENKINS_HOME}/runtime/java/.script 目录下,可以根据个人需要进行动态调整
接下来我们需要编写 post success 脚本,将这些工具复制过来,并执行脚本生成 .env 文件,这些生成的文件全部放在 target 目录下
stage('Compile-Package') {
tools { ... }
steps { ... }
post {
success {
sh '''
cd target
cp ${JENKINS_HOME}/runtime/java/.script/docker-compose.yaml ./
cp ${JENKINS_HOME}/runtime/java/.script/run.sh ./
cp ${JENKINS_HOME}/runtime/java/.script/env-setup.sh ./
bash ./env-setup.sh \
--run-dir="./" --con-name=test-hook \
--exec-script="java -jar ${JAR_NAME}" \
--host-port=8192 --con-port=8080 --java-version=21
'''
}
}
}
2.5 远程部署
现在程序包和docker相关文件已经准备完毕,接下来需要将其部署到远程主机,点击流水线左下方的 流水线语法 进入流水线生成页面
示例步骤处选择 sshPublisher
在配置完这些之后可根据个人需求,点击高级下拉菜单,进行修改。最后点击下方的 生成流水线脚本 生成相关脚本,并填入 pipeline 中
stages {
...
stage('Remote-Deploy') {
steps {
// 这里使用脚本区域,判断 .env 文件是否正确生成,如果没问题则进行传输
script {
if (fileExists("./target/.env")) {
sshPublisher(publishers: [sshPublisherDesc(configName: 'Host_Server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''cd /home/jenkins/docker/runtime/java/test-hook
sudo docker-compose up -d''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '${PROJECT_NAME}', remoteDirectorySDF: false, removePrefix: 'target', sourceFiles: 'target/${JAR_NAME}, target/docker-compose.yaml, target/.env, target/run.sh')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
} else {
sh 'echo ".env file not generated"'
}
}
}
}
}
2.6 汇总
pipeline {
agent any
environment {
PROJECT_NAME = "test-hook"
JAR_NAME = "test-hook-${JAR_VERSION}.jar"
}
stages {
stage('Checkout') {
steps {
git branch: 'main', credentialsId: 'jenkins-github-host-private-key', poll: false, url: 'git@github.com:EmyiaEllen/test-hook.git'
}
}
stage('Compile-Package') {
tools {
jdk 'OpenJDK21'
maven 'apache-maven-3.9.9'
}
steps {
sh 'mvn -Dmaven.test.failure.ignore=true clean package'
}
post {
success {
sh '''
cd target
cp ${JENKINS_HOME}/runtime/java/.script/docker-compose.yaml ./
cp ${JENKINS_HOME}/runtime/java/.script/run.sh ./
cp ${JENKINS_HOME}/runtime/java/.script/env-setup.sh ./
bash ./env-setup.sh \
--run-dir="./" --con-name=test-hook \
--exec-script="java -jar ${JAR_NAME}" \
--host-port=8192 --con-port=8080 --java-version=21
'''
}
}
}
stage('Remote-Deploy') {
steps {
script {
if (fileExists("./target/.env")) {
sshPublisher(publishers: [sshPublisherDesc(configName: 'Host_Server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''cd "/home/jenkins/docker/runtime/java/test-hook"
sudo docker-compose up -d''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '${PROJECT_NAME}', remoteDirectorySDF: false, removePrefix: 'target', sourceFiles: 'target/${JAR_NAME},target/.env,target/docker-compose.yaml,target/run.sh')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
} else {
sh 'echo ".env file not generated"'
}
}
}
}
}
}
3. 构建
1. 手动构建
点击 test-hook-pipeline 条目,并点击 Build With Parameters 构建
最后进入远程主机,使用 sudo docker ps -a 和 sudo docker logs -f <CONTAINER_ID> 验证容器是否构建成功
2. Github WebHook 构建
进入 Github 仓库,点击上方的 Setting 进入设置页面
点击左侧的 Webhooks 进入 Webhooks 页面,并点击上方的 Add Webhook
在 Payload URL 这里,输入主机IP和 Jenkins 容器占用的端口,路径为 /github-webhook/
点击下方的 Add Webhook 确认添加,等待一会后刷新,如果出现对勾则说明验证成功
在 Windows 上尝试修改并 push 到 Github,验证 Github Webhook 是否可用
随后来到 Jenkins 页面,可以看到已经触发了一个新的任务
等待构建完毕后,通过 HTTP 访问进行验证