Jenkins 是一个基于 Java 的自动化服务器。过插件生态扩展能力,实现软件开发全流程自动化,是目前最流行的开源持续集成/持续部署(CI/CD)工具。
一、Jenkins 能做什么?
它能自动拉代码、编译、测试、打包、构建 Docker 镜像、推送镜像、SSH 登录服务器、自动部署。
二、安装 Jenkins
不建议直接裸机安装,一般都是 Docker 安装 Jenkins。因为干净、好迁移、好备份,企业一般都是容器化。
1. Jenkins + Docker Compose 安装
正如你所见,Docker 是负责构建镜像、启动容器、隔离环境、提供容器运行时。例如,
docker run -d nginx
但是,现代企业微服务服务太多,如果直接使用 Docker 的话,那么就需要:
docker run ...
docker run ...
docker run ...
docker network create ...
docker volume create ...
每个服务都要这样来一遍,会非常痛苦。
1.1创建目录
sudo mkdir -p /opt/deploy/jenkins/home /opt/deploy/jenkins/maven
1.2 编写 docker-compose.yml
version: '3'
services:
jenkins:
image: jenkins/jenkins:2.516.3-jdk17
container_name: jenkins
restart: always
ports:
- "8080:8080"
- "50000:50000"
volumes:
- /opt/deploy/jenkins/home:/var/jenkins_home
- /opt/deploy/jenkins/maven:/root/.m2
- /var/run/docker.sock:/var/run/docker.sock
- /usr/bin/docker:/usr/bin/docker
user: root
environment:
- TZ=Asia/Shanghai
mem_limit: 1G
其中,
/var/run/docker.sock
是为了让 Jenkins 能调用宿主机 Docker。
1.3 启动
sudo docker-compose up -d
#查看启动日志
sudo docker-compose logs
不出意外的话,你可以在日志中看到 Jenkins 的临时密码。如果没看到,也不用担心。
# 查看管理员密码 因为Jenkins的/var/jenkins_home目录挂载到了 /opt/deploy/jenkins/home
cat /opt/deploy/jenkins/home/secrets/initialAdminPassword
# 或者进入 Jenkins 容器
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
1.4 访问 Jenkins
http://你的IP:8080
1.4.1 安装必要插件
登录进入 Jenkins 网站之后,选择“自定义安装插件”卡片,这个卡片也会默认勾选一些插件,直接点确认即可。后面再按需安装我们需要的插件。
# 必须安装
Pipeline
Docker Pipeline
Git
Gitee
SSH
Publish Over SSH
# 推荐安装
Blue Ocean
Role-based Authorization
1.4.2 配置 maven
生产环境里,Docker 官方的 Jenkins 镜像不自带 Maven,这是刻意设计的。最佳实践通常不是“往 Jenkins 容器里手动安装 Maven”,而是把 Jenkins Controller 做轻量化,把构建环境外置。
目前生产上推荐的主流方案有2个。
方案一:使用 Jenkins Agent
这是现在最标准、最符合云原生/DevOps 的方案。
架构:
Jenkins Controller
|
| 调度任务
v
Jenkins Agent(带 Maven/JDK)
Jenkins 官方也明确推荐这种方案,因为这种说法 Controller 不负责编译、所有构建工具放在 Agent,Agent 可按项目隔离环境。
具体做法:
FROM jenkins/jenkins:2.516.3-jdk17
USER root
RUN apt-get update && \
apt-get install -y maven openjdk-17-jdk
USER jenkins
这个 Dockerfile 文件放在跟 docker-compose.yml 同一级的目录。
然后构建自定义的 Jenkins。
docker build -t my-jenkins-agent:maven17 .
最后在 Jenkins 中创建声明式流水线项目,Pipeline 文件内容可以如下配置:
pipeline {
agent {
docker {
image 'my-jenkins-agent:maven17'
}
}
stages {
stage('Build') {
steps {
sh 'mvn clean package'
}
}
}
...
...
}
方案二:Pipeline 里直接使用 Maven Docker 镜像
这是目前非常现代化的做法,是中小团队最省事的做法。它完全不用自己维护Maven、官方镜像、环境一致、CI/CD 可复现、升级简单
具体做法:
pipeline {
agent any
stages {
stage('Build') {
agent {
docker {
image 'maven:3.6.3-jdk-8'
}
}
steps {
sh 'mvn -v'
sh 'mvn clean package'
}
}
}
}
但是这个方案有个隐患,每次构建都会重新下载依赖会影响构建速度。正确的做法是挂载 Maven Cache,缓存 Maven 本地仓库。
agent {
docker {
image 'maven:3.6.3-jdk-8'
# 挂载 maven cache
args '-v /var/maven-repo:/root/.m2'
}
}
三、配置 Jenkins 凭据
首先登录 Jenkins UI 页面 http://ip:8080,进入
Manage Jenkins → Security模块 → Credentials
1. 添加 Gitee Token
点击“Add Credentials”按钮,选择类型:
Username with password
填写username、password等信息
用户名:
填写你的Gitee用户名
密码:
Gitee私人令牌
填写ID
gitee-token
2. 添加服务器 SSH 登录
点击“Add Credentials”按钮,选择类型:
SSH Username with private key
填写username、password等信息
用户名:
root
私钥:
你的 ~/.ssh/id_rsa
ID:
A1-ssh
四、创建 Pipeline 任务(正式开始部署)
进入 Jenkins 首页,选择:
New Item 或 新建作业
输入项目名称:
dsc-dev-micro-base-deploy
选择项目类型(select an item type):
Pipeline
最后点击 OK。
1. General 配置
勾选“Discard old builds 或 捨棄舊建置”,将“建構保留天數”设置为30,“建置保留次數”设置为7.
2. Triggers 触发器配置
勾选含有“Gitee Triggers”字样的选项,其它啥也不用改
3. 配置 Pipeline
Definition 选择 Pipeline Script。然后粘贴:
pipeline {
agent any
environment {
REGISTRY = "http://39.99.217.173:50000"
NAMESPACE = "dev"
PROD_HOST = "47.95.251.38"
TAG = "${BUILD_NUMBER}"
}
stages {
stage('Checkout Code:代码检测') {
steps {
git(
branch: 'master',
credentialsId: 'gitee-token',
url: 'https://gitee.com/miki0953/micro-base.git'
)
}
}
stage('Maven Build:构建') {
agent {
docker {
image 'maven:3.6.3-jdk-8'
args '-v /root/.m2:/root/.m2'
}
}
steps {
sh '''
mvn clean package \
-Dmaven.test.skip=true
'''
}
}
stage('Build Docker Images') {
parallel {
stage('Build Auth:构建认证服务') {
steps {
dir('micro-auth') {
sh """
docker build \
-t ${REGISTRY}/${NAMESPACE}/micro-auth:${TAG} \
.
docker tag \
${REGISTRY}/${NAMESPACE}/micro-auth:${TAG} \
${REGISTRY}/${NAMESPACE}/micro-auth:latest
"""
}
}
}
stage('Build Gateway:构建网关服务') {
steps {
dir('micro-gateway') {
sh """
docker build \
-t ${REGISTRY}/${NAMESPACE}/micro-gateway:${TAG} \
.
docker tag \
${REGISTRY}/${NAMESPACE}/micro-gateway:${TAG} \
${REGISTRY}/${NAMESPACE}/micro-gateway:latest
"""
}
}
}
}
}
stage('Push Images') {
steps {
sh """
echo "$DOCKER_PASS" | docker login \
--username "$DOCKER_USER" \
--password-stdin \
${REGISTRY}
docker push ${REGISTRY}/${NAMESPACE}/micro-auth:${TAG}
docker push ${REGISTRY}/${NAMESPACE}/micro-auth:latest
docker push ${REGISTRY}/${NAMESPACE}/micro-gateway:${TAG}
docker push ${REGISTRY}/${NAMESPACE}/micro-gateway:latest
"""
}
}
stage('Deploy') {
steps {
sshagent(['A1-ssh']) {
sh """
ssh -o StrictHostKeyChecking=no root@${PROD_HOST} << EOF
cd /opt/deploy/registry/data
docker-compose pull
docker-compose up -d
docker image prune -f
EOF
"""
}
}
}
}
post {
success {
echo 'Deploy Success:发布成功'
}
failure {
echo 'Deploy Failed:发布失败'
}
}
}
五、配置 Gitee Webhook
登录 Gitee,进入
仓库 → 管理 → WebHooks
点击“添加 WebHooks”,填写URL
http://JENKINS_IP:8080/gitee-project/Jenkins新建作业时填写的项目名称
#例如
http://39.99.217.173:8080/gitee-project/dsc-dev-micro-base-deploy
六、过程中出现的问题
问题1. Jenkins 所在服务器无法访问 Docker Hub: registry-1.docker.io 连接超时
这是国内服务器最常见的问题。报错日志:docker pull maven:3.6.3-jdk-8 Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers) script returned exit code 1
事实上,我们已经配置了 Docker 镜像加速器,但还是去访问了 Docker Hub,说明配置的镜像加速器里也没有我们需要的镜像。
解决方案:提前拉取镜像
在 Jenkins 机器提前手动拉取 docker pull maven:3.6.3-jdk-8;这样之后 Pipeline 的时候就不会再 pull。因为本地已有镜像
问题2. Docker agent 导致 Jenkins workspace 被切换了
这是 Declarative Pipeline + Docker Agent 的经典坑 mvn clean package -Dmaven.test.skip=true
报错日志:
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.223 s
[INFO] Finished at: 2026-05-11T02:19:00Z
[INFO] ------------------------------------------------------------------------
[ERROR] The goal you specified requires a project to execute but there is no POM in this directory (/var/jenkins_home/workspace/dsc-dev-micro-base-deploy@2). Please verify you invoked Maven from the correct directory. -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MissingProjectException
原因分析:当 Jenkins 进入:docker agent 时。它不会直接使用:/workspace/dsc-dev-micro-base-deploy 。而是:重新创建一个临时 workspace ,类似:/workspace/dsc-dev-micro-base-deploy@2。然后把代码挂载进去。但为什么 @2 里面没文件,这是关键。因为 git checkout 是在主 agent 完成的。但 docker agent 切换时。Jenkins 并没有把 workspace 正确同步进去。因此 @2 目录为空,所以 Maven 执行 mvn clean package 时没有 pom.xml。
Declarative Pipeline agent docker 底层其实是 docker run -v workspace:/workspace 但 workspace 锁、parallel、reuseNode、容器 agent、Jenkins Docker Plugin 之间会有复杂行为。于是 workspace@2 空目录是非常常见的问题。
解决方案:加入 reuseNode true,reuseNode true 表示 Docker 容器复用当前 Jenkins 节点 workspace, 而不是重新创建 @2 workspace
agent {
docker {
image 'maven:3.6.3-jdk-8'
args '-v /root/.m2:/root/.m2'
reuseNode true
}
}
现在 Docker 容器直接使用 /workspace/dsc-dev-micro-base-deploy。
问题3. Docker 镜像名格式错误
报错日志:docker build -t http://39.99.217.173:50000/dev/micro-auth:6 . invalid argument "http://39.99.217.173:50000/dev/micro-auth:6" for "-t, --tag" flag: invalid reference format
原因分析:Docker 镜像 tag 不能带协议头。Docker 不允许 http://,因为 Docker 镜像名不是 URL。Docker 会自己决定 http、https协议。所以 tag 只能是 registry 地址,不能是完整 URL。
解决方案,将:
environment {
REGISTRY = "http://39.99.217.173:50000"
}
改成:
environment {
REGISTRY = "39.99.217.173:50000"
}
问题4. 推送 Images 失败
报错日志:docker push 39.99.217.173:50000/dev/micro-auth:11 The push refers to repository [39.99.217.173:50000/dev/micro-auth] Get http://39.99.217.173:50000/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
原因分析:核心错误是 docker push 39.99.217.173:50000/dev/micro-auth:11 返回 Get http://39.99.217.173:50000/v2/:net/http: request canceled while waiting for connection
意思 Jenkins 无法连接私有 Registry 不是认证失败,是网络连接不上。
解决方案:根本原因在于 Registry 实际监听的 5000 端口,但是却 push:docker push 39.99.217.173:50000/... 所以超时。将端口改过来就行
environment {
REGISTRY = "39.99.217.173:5000"
}
问题5. Deploy 阶段 SSH 登录失败
报错日志:ssh -o StrictHostKeyChecking=no root@47.95.251.38 Pseudo-terminal will not be allocated because stdin is not a terminal. Warning: Permanently added '47.95.251.38' (ED25519) to the list of known hosts. Permission denied, please try again. Permission denied, please try again. root@47.95.251.38: Permission denied (publickey,password).
原因分析:核心错误 Permission denied (publickey,password) 意思是 Jenkins 无法通过 SSH 登录生产服务器。从 Pipeline 文件配置的是 sshagent(['A1-ssh']) 说明使用的是 SSH 私钥认证,但服务器不接受这个私钥——要么是在 Manage Jenkins → Security模块 → Credentials 里没有配置,要么是配置错了。
sshagent 说明:sshagent(['A1-ssh']) 作用只是把 Jenkins 保存的私钥注入到 ssh-agent,但前提必须是服务器 authorized_keys 里有对应公钥,否则认证一定失败。Jenkins ssh-agent 只支持 SSH Key
解决方案:重新配置 SSH 密钥
第一步:在 Jenkins 机器生成密钥
进入 Jenkins 容器:
docker exec -it jenkins bash
生成:
ssh-keygen -t rsa
一路回车。
会生成:
/root/.ssh/id_rsa
/root/.ssh/id_rsa.pub
第二步:把公钥上传到生产服务器
查看公钥并复制:
cat ~/.ssh/id_rsa.pub
第三步:登录生产服务器
执行:
mkdir -p /root/.ssh
vim /root/.ssh/authorized_keys
把公钥追加进去
第四步:设置权限
chmod 700 /root/.ssh
chmod 600 /root/.ssh/authorized_keys
第五步:测试 SSH
回 Jenkins 机器:
ssh root@47.95.251.38
如果无需密码直接登录,说明成功
第六步:Jenkins Credentials 配置
进入 Jenkins:
Manage Jenkins → Security模块 → Credentials
新建:
SSH Username with private key
用户名:
root
私钥填内容:
cat ~/.ssh/id_rsa
ID:
A1-ssh