Jenkins如何一步步部署Spring Cloud微服务

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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
禁止转载,如需转载请通过简信或评论联系作者。

相关阅读更多精彩内容

友情链接更多精彩内容