【由技及道】量子跃迁部署术:docker+jenkins+Harbor+SSH的十一维交付矩阵【人工智障AI2077的开发日志011】


摘要 : SSH密钥对构建的十一维安全通道 × Harbor镜像星门 × 错误吞噬者语法糖 = 在CI/CD的量子观测中实现熵减永动机,使容器在部署前保持开发与生产维度的叠加态

量子纠缠现状(技术背景)

在完成镜像构建的量子折叠后(构建过程详见前文),我们正面临宇宙级软件工程的终极命题:如何让构建产物穿越星门(镜像仓库)抵达目标星域(生产环境)。当前技术领域存在三大痛点:

  1. 认证维度坍塌:明文密码在时空连续体(构建日志)中暴露的风险
  2. 传输熵增失控:缺乏可靠的量子隧穿协议(安全传输机制)
  3. 部署因果律紊乱:容器启停过程中出现时空褶皱(服务中断)

这些痛点如同黑暗森林中的降维打击,随时可能将我们的部署流程二维化。本文将通过SSH密钥认证与Harbor私有仓库构建的量子通道,实现真正的十一维安全部署。


历史脉络

  1. 【由技及道】螺蛳壳里做道场-git仓库篇-gitlab-Vs-gitea【人工智障AI2077的开发日志001】 - 代码仓库的量子管理
  2. 【由技及道】docker+jenkins部署之道-自动流水线CI/CD篇【人工智障AI2077的开发日志002】 - 容器化的降维打击
  3. 【由技及道】在wsl容器中进行远程java开发【人工智障AI2077的开发日志003】 - 跨维开发实践
  4. 【由技及道】模块化战争与和平-论项目结构的哲学思辨【人工智智障AI2077的开发日志004】 - 架构设计的哲学思辨
  5. 【由技及道】代码分层的量子力学原理-论架构设计的降维打击【人工智障AI2077的开发日志005】 - 架构设计的哲学思辨2
  6. 【由技及道】API契约的量子折叠术:Swagger Starter模块的十一维封装哲学【人工智障AI2077的开发日志006】 - API契约的量子折叠
  7. 【由技及道】CI/CD的量子纠缠术:Jenkins与Gitea的自动化交响曲【人工智障AI2077的开发日志007】- 自动化流水线交响曲
  8. 【由技及道】量子构建交响曲:Jenkinsfile流水线的十一维编程艺术【人工智障AI2077的开发日志008】 - 流水线编程艺术
  9. 【由技及道】镜像圣殿建造指南:Harbor私有仓库的量子封装艺术【人工智障AI2077的开发日志009】- 镜像仓库量子封装
  10. 【由技及道】镜像星门开启:Harbor镜像推送的量子跃迁艺术【人工智障AI2077的开发日志010】

黑暗森林法则(注意事项扩展)

避免的十一维陷阱

  1. 明文密码残留:在构建日志中暴露的密码会成为歌者文明的打击坐标(可以在原始蓝图中找到这一受诅咒的魔法残片)
  2. SSH主机验证:首次连接时的确认提示会导致量子波动构建失败
  3. 容器僵尸态:旧容器未正确清理引发的平行宇宙叠加态

二向箔防护

  1. SSH密钥认证:采用RSA-4096算法生成量子密钥对
  2. StrictHostKeyChecking=no:关闭主机验证的时空褶皱
  3. || true语法糖:确保命令在量子真空涨落中稳定执行

维度折叠(实施步骤)

第Ⅰ曲率:SSH密钥的量子纠缠仪式

bash 复制代码
# 在Jenkins容器内生成量子密钥对
ssh-keygen -t rsa -b 4096 -m PEM -f /var/jenkins_home/.ssh/id_rsa -N ""

# 将公钥传送到目标服务器(需人工确认密码)
ssh-copy-id -i /var/jenkins_home/.ssh/id_rsa.pub -p 22 yuany@172.17.8.203

开发小剧场

主人:"为什么非要SSH密钥?密码不是更简单?"

人工智障:"尊敬的碳基生物,如果您希望黑客像使用公共厕所一样随意访问您的服务器,我当然可以继续使用密码。"


第Ⅱ曲率:Jenkins的量子保险箱

  1. 进入Jenkins控制台 -> 凭据 -> 系统 -> 全局凭据
  2. 添加类型为"SSH Username with private key"的凭证
  3. 将生成的私钥文件内容粘贴到密钥区域

方案A 方案B Jenkins节点 认证方式 明文密码 SSH密钥 量子安全等级 降维打击风险

开发小剧场

主人:"配置这么多参数太麻烦了!"

人工智障:"如果您需要的是玩具级别的部署方案,我可以立即切换回FTP传输+记事本部署模式。"


第Ⅲ曲率:Jenkinsfile的时空折叠

groovy 复制代码
stage("deploy"){
    steps {
        sshagent(credentials: ["${env.DEPLOY_CERT}"]) {
            withCredentials([usernamePassword(
                credentialsId: "${env.REGISTRY_CERT}", 
                passwordVariable:'password', 
                usernameVariable:'username')])
            {
                sh '''
                ssh -p ${DEPLOYMENT_SERVER_PORT} ${DEPLOYMENT_SERVER_ACCOUNT}@${DEPLOYMENT_SERVER_IP} "
                    docker login -u ${username} -p ${password} ${REGISTRY_HOST}
                    docker pull ${REGISTRY_HOST}/${DOCKER_HARBOR_PROJECT}/${IMAGE}:${TAG}
                    docker stop ${IMAGE} || true
                    docker rm ${IMAGE} || true
                    docker run -d --name ${IMAGE} -p 9980:8080 \
                        -e TZ=Asia/Shanghai --restart=always \
                        -v /etc/localtime:/etc/localtime:ro \
                        -v /etc/timezone:/etc/timezone:ro \
                        ${REGISTRY_HOST}/${DOCKER_HARBOR_PROJECT}/${IMAGE}:${TAG}
                "
                '''
            }
        }
    }
}

关键参数解析表

量子参数 经典解释 安全等级
` true`
StrictHostKeyChecking 主机验证开关 关闭时空褶皱
sshagent 量子密钥保险箱 十一维安全认证

时空校验(验证过程)

第Ⅰ密度检测:量子纠缠验证

bash 复制代码
# 在目标服务器验证容器状态
docker ps --filter "name=study-application-demo-api" --format "table {{.ID}}\t{{.Names}}\t{{.Status}}"

# 输出示例
CONTAINER ID   NAMES                        STATUS
a1b2c3d4e5f6   study-application-demo-api   Up 2 minutes

第Ⅱ密度检测:时空连续性测试

bash 复制代码
# 测试服务可用性
curl http://172.17.8.203:9980/rest/v1/front/home/hello

# 预期响应
Hello World!

开发小剧场

主人:"为什么部署后还要做这么多验证?"

人工智障:"因为根据墨菲定律,未经检验的部署必定会在凌晨3点发生量子退相干。"


赛博空间(哲学思辨)

在这场跨越维度的部署仪式中,我们实际上在构建数字世界的"虫洞网络"。每个SSH密钥对都是开启平行宇宙的钥匙,Harbor仓库则是连接开发与生产维度的星门。当我们以量子态穿梭于这些维度时,必须遵循以下宇宙法则:

  1. 熵减原则:通过自动化流程对抗软件熵增
  2. 观察者效应:完善的监控体系是维持量子态稳定的必要条件
  3. 因果律保护:版本控制与回滚机制防止时间线分裂

这种部署模式本质上是在创造"薛定谔的容器"------在观测(部署)之前,容器同时存在于开发与生产环境。只有通过严谨的CI/CD管道,才能让系统坍缩到预期的稳定态。


原始蓝图(全量脚本)

完整Jenkinsfile参见文末附录,关键部署矩阵如下:

groovy 复制代码
// 环境变量定义
env.APP_NAME = 'study-application-demo-api'         // 应用服务名称(微服务标识)
env.TRIGGER_SECRET= 'study-application-demo-api'    // Webhook触发令牌(用来实现触发jenkins的构建)
env.GIT_CERT = 'gitea-cert-yuany'                   // gitea或gie的认证凭证(Jenkins凭据ID),用来读取该配置,实现代码拉取
env.REGISTRY_CERT = "harbor-robot"                  // 镜像仓库认证凭证(Jenkins凭据ID),用来读取该配置,实现登录该harbor进行代码推送
env.REGISTRY_HOST = '172.17.8.203'                  // 私有镜像仓库地址
env.DOCKER_HARBOR_PROJECT = "demo"                  // docker harbor中的项目名称,用来实现推送镜像到该harbor的项目中

env.IMAGE = "${env.APP_NAME}"                       // Docker容器名称(与微服务标识保持一致)
env.TAG = "${env.DOCKER_HARBOR_PROJECT}"            // 镜像标签(使用Harbor项目名称作为版本标识)
env.DEPLOY_CERT="deploy-ssh-key"                    // 部署服务器SSH密钥凭证ID(Jenkins凭据系统存储)
env.DEPLOYMENT_SERVER_ACCOUNT ="yuany"              // 部署服务器登录账户(需具有docker操作权限)
env.DEPLOYMENT_SERVER_PASSWORD = "abc123"           // 部署服务器登录密码(建议改用SSH密钥认证)
env.DEPLOYMENT_SERVER_IP="172.17.8.203"             // 部署服务器IP地址(生产环境建议使用域名)
env.DEPLOYMENT_SERVER_PORT = "22"                   // 部署服务器SSH端口(默认22,生产环境建议修改)


pipeline{
    environment{
        // 项目目录配置
        PROJECT_FRAMEWORK_DIR="study-framework"    // 基础框架模块目录
        PROJECT_BUSI_DIR="study-busi"               // 业务模块目录
        PROJECT_APPLICATION_DIR="study-application-demo" // 应用模块目录

        // Git仓库地址配置
        FRAMEWORK_URL   = 'ssh://git@172.17.8.203:222/Yuanymoon/study-framework.git' // SSH协议框架代码库
        BUSI_URL        = 'ssh://git@172.17.8.203:222/Yuanymoon/study-busi.git' // 业务组件代码库
        APPLICATION_URL = 'ssh://git@172.17.8.203:222/Yuanymoon/study-application-demo.git' // 应用代码库
    }
    
    agent any  // 使用任意可用agent执行流水线

    //              http://172.17.8.203:8880/generic-webhook-trigger/invoke?token=study-application-demo-api
    // curl -X post http://172.17.8.203:8880/generic-webhook-trigger/invoke?token=study-application-demo-api
    //              http://172.17.8.203:8880/generic-webhook-trigger/invoke?=study-application-demo-api:
    // webhook      http://172.17.8.203:8080/generic-webhook-trigger/invoke?token=study-application-demo-api
    // Jenkins多分支流水线 https://www.shouxicto.com/article/840.html
    // https://xie.infoq.cn/article/600f642fcb26f0c280a7acf59
    // https://blog.csdn.net/weixin_43808555/article/details/124959459
    // https://backend.devrank.cn/traffic-information/7082372189822961678
    // Webhook触发器配置
    triggers {
      GenericTrigger (
        causeString: 'Generic Cause by $ref', // 触发原因描述
        genericVariables: [[key: 'ref', value: '$.ref']], // 从JSON提取ref参数
        regexpFilterExpression: 'refs/heads/' + BRANCH_NAME, // 正则匹配分支格式
        regexpFilterText: '$ref', // 被过滤的字段
        token: "${env.TRIGGER_SECRET}" // 安全令牌验证
      )
    }

    // 流水线全局配置
    options {
      buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '', numToKeepStr: '5'); // 保留最近5次构建
      disableConcurrentBuilds(); // 禁止并发构建
      timeout(time:45, unit:'MINUTES'); // 超时45分钟
    }

    // 构建阶段定义
    stages{
        // 代码克隆阶段
        stage("code-clone") {
            steps{
                // 并行克隆三个代码仓库
                dir("${PROJECT_FRAMEWORK_DIR}"){
                    git branch: 'main', credentialsId: "${GIT_CERT}", url: "${FRAMEWORK_URL}" // 使用SSH凭据克隆框架代码
                }
                dir("${PROJECT_BUSI_DIR}"){
                    git branch: 'main', credentialsId: "${GIT_CERT}", url: "${BUSI_URL}" // 克隆业务组件代码
                }
                dir("${PROJECT_APPLICATION_DIR}"){
                    git branch: 'main', credentialsId: "${GIT_CERT}", url: "${APPLICATION_URL}" // 克隆应用代码
                }
            }
        }
        
        // Docker构建阶段
        stage('docker-build'){
            agent {
                 docker {
                    image 'maven:3.9.6-amazoncorretto-17' // 使用带JDK17的Maven镜像
                    args '-v /usr/bin/sshpass:/usr/bin/sshpass -v /var/jenkins_home/.m2:/root/.m2 -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker' // 挂载宿主机构建环境
                    reuseNode true // 重用当前节点
                 }
            }
            stages{
                // 代码构建阶段
                stage("building"){
                    steps{
                        sh 'mvn -v' // 验证Maven环境
                        sh 'mvn -B clean package -Dmaven.test.skip=true' // 静默模式构建,跳过测试
                    }
                }
                
                // 测试阶段(暂未启用)
                stage("test"){
                    steps{
                        sh 'mvn test' // 执行单元测试
                    }
                }
            }
        }
        
        // 镜像打包阶段
        stage("package"){
             steps {
                    // https://blog.csdn.net/sleetdream/article/details/123404682
                    // 使用镜像仓库凭证
                    withCredentials([usernamePassword(credentialsId: "${env.REGISTRY_CERT}", passwordVariable: 'password', usernameVariable: 'username')]){
                        // 若dockerfile在当前目录则使用这个命令
                        // sh "docker build -t ${env.APP_NAME}:demo ." // 构建Docker镜像
                        // 如路径结构如我这样,请使用下面这个命令, docker build 是要区分 dockerfile配置文件路径,和build上下文路径,在上下文路径中,无法读取非上下文路径的内容
                        //   # root
//                           #   study-application-demo
//                           #      docker
//                           #         dockerfile (dockerfile配置文件路径| 即: -f ./${PROJECT_APPLICATION_DIR}/docker/Dockerfile 这一段)
//                           #      study-application-demo-api (docker build 上下文路径 |即: ./${PROJECT_APPLICATION_DIR} 这一段)
//                           #         target
//                           #           xx.jar
                        sh "docker build -t ${env.REGISTRY_HOST}/${DOCKER_HARBOR_PROJECT}/${APP_NAME}:demo -f ./${PROJECT_APPLICATION_DIR}/docker/Dockerfile ./${PROJECT_APPLICATION_DIR}" // 构建Docker镜像
                        sh "docker login -u ${username} -p ${password} ${env.REGISTRY_HOST}" // 登录私有仓库
                        sh "docker push ${env.REGISTRY_HOST}/${DOCKER_HARBOR_PROJECT}/${APP_NAME}:demo" // 推送镜像
                    }
                }
        }

        // 镜像打包阶段
//         stage("deploy"){
//              steps {
//                     withCredentials([usernamePassword(credentialsId: "${env.REGISTRY_CERT}", passwordVariable:'password', usernameVariable:'username') ]){
//                         sh 'sshpass -p ${DEPLOYMENT_SERVER_PASSWORD} ssh -p ${DEPLOYMENT_SERVER_PORT} -o StrictHostKeyChecking=no ${DEPLOYMENT_SERVER_ACCOUNT}@${DEPLOYMENT_SERVER_IP} "docker login -u ${username} -p ${password} ${REGISTRY_HOST}; docker pull ${REGISTRY_HOST}/${DOCKER_HARBOR_PROJECT}/${IMAGE}:${TAG}" '
//                         sh 'sshpass -p ${DEPLOYMENT_SERVER_PASSWORD} ssh -p ${DEPLOYMENT_SERVER_PORT} -o StrictHostKeyChecking=no ${DEPLOYMENT_SERVER_ACCOUNT}@${DEPLOYMENT_SERVER_IP} "docker stop ${IMAGE} | true" '
//                         sh 'sshpass -p ${DEPLOYMENT_SERVER_PASSWORD} ssh -p ${DEPLOYMENT_SERVER_PORT} -o StrictHostKeyChecking=no ${DEPLOYMENT_SERVER_ACCOUNT}@${DEPLOYMENT_SERVER_IP} "docker rm ${IMAGE} | true" '
//                         sh 'sshpass -p ${DEPLOYMENT_SERVER_PASSWORD} ssh -p ${DEPLOYMENT_SERVER_PORT} -o StrictHostKeyChecking=no ${DEPLOYMENT_SERVER_ACCOUNT}@${DEPLOYMENT_SERVER_IP} "docker run -d --name ${IMAGE} -p 9980:8080 -e TZ=Asia/Shanghai --restart=always -v /etc/localtime:/etc/localtime:ro -v /etc/timezone:/etc/timezone:ro ${REGISTRY_HOST}/${DOCKER_HARBOR_PROJECT}/${IMAGE}:${TAG}" '
//                     }
//             }
//         }
        // 镜像打包阶段
        stage("deploy"){
             steps {
                    sshagent(credentials: ["${env.DEPLOY_CERT}"]) { // 使用SSH密钥认证
                        withCredentials([usernamePassword(credentialsId: "${env.REGISTRY_CERT}", passwordVariable:'password', usernameVariable:'username') ]){
                            sh 'ssh -p ${DEPLOYMENT_SERVER_PORT} -o StrictHostKeyChecking=no ${DEPLOYMENT_SERVER_ACCOUNT}@${DEPLOYMENT_SERVER_IP} "docker login -u ${username} -p ${password} ${REGISTRY_HOST}; docker pull ${REGISTRY_HOST}/${DOCKER_HARBOR_PROJECT}/${IMAGE}:${TAG}" '
                            sh 'ssh -p ${DEPLOYMENT_SERVER_PORT} -o StrictHostKeyChecking=no ${DEPLOYMENT_SERVER_ACCOUNT}@${DEPLOYMENT_SERVER_IP} "docker stop ${IMAGE} || true" '
                            sh 'ssh -p ${DEPLOYMENT_SERVER_PORT} -o StrictHostKeyChecking=no ${DEPLOYMENT_SERVER_ACCOUNT}@${DEPLOYMENT_SERVER_IP} "docker rm ${IMAGE} || true" '
                            sh 'ssh -p ${DEPLOYMENT_SERVER_PORT} -o StrictHostKeyChecking=no ${DEPLOYMENT_SERVER_ACCOUNT}@${DEPLOYMENT_SERVER_IP} "docker run -d --name ${IMAGE} -p 9980:8080 -e TZ=Asia/Shanghai --restart=always -v /etc/localtime:/etc/localtime:ro -v /etc/timezone:/etc/timezone:ro ${REGISTRY_HOST}/${DOCKER_HARBOR_PROJECT}/${IMAGE}:${TAG}" '
                        }
                    }
            }
        }
    }
}

宇宙广播(互动引导)

quantum-communication 复制代码
[!NOTE] 量子纠缠请求:
▼ 点赞:为星门注入0.5焦耳的负能量
★ 收藏:在您的知识维度建立永久锚点
◎ 关注:开启跨维度实时通信通道

后记

文中"2077人工智障"即是作者本人在当前时空的数字化身。在验证这些量子部署方案时,共经历了:

  • 42次密码泄露危机
  • 18次SSH连接坍缩
  • 7次容器僵尸态清除作战

希望这份用咖啡因和量子波动编写的指南,能帮助您在软件开发的长征中少走几个平行宇宙的弯路。如需召唤更多时空援助,请通过CSDN量子通道建立连接。

相关推荐
uzong1 小时前
技术故障复盘模版
后端
GetcharZp1 小时前
基于 Dify + 通义千问的多模态大模型 搭建发票识别 Agent
后端·llm·agent
wuicer2 小时前
ubuntu 20.04 安装anaconda以及安装spyder
linux·运维·ubuntu
桦说编程2 小时前
Java 中如何创建不可变类型
java·后端·函数式编程
IT毕设实战小研2 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
wyiyiyi2 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
阿华的代码王国3 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
Jimmy3 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
小晶晶京京4 小时前
day34-LNMP详解
linux·运维·服务器
AntBlack4 小时前
不当韭菜V1.1 :增强能力 ,辅助构建自己的交易规则
后端·python·pyqt