You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jenkins流水线Docker部署回滚及容器移除异常求助

Jenkins持续部署流水线问题修复方案

问题1:回滚时提示找不到镜像

问题原因

  • 部署仅推送带${env.BUILD_NUMBER}标签的镜像,未同步推送latest标签作为稳定版本标记,本地也不存在无标签镜像(Docker默认拉取latest标签,原命令未指定标签导致匹配失败)。
  • 回滚命令未指定具体稳定版本,直接使用无标签镜像触发查找失败。

修复方案

  1. 在镜像推送环节新增latest标签推送,标记当前成功构建为稳定版本
  2. 回滚时明确指定latest标签拉取稳定镜像

修改后的deployContainer函数

def deployContainer(imageName) {
    docker.withRegistry('https://registry.hub.docker.com', 'dockerhub_credentials') {
        def customImage = docker.build("${env.DOCKER_REPO}/${imageName}:${env.BUILD_NUMBER}")
        // 推送带构建号的镜像
        customImage.push()
        // 推送latest标签镜像,标记为当前稳定版本
        customImage.push('latest')
    }
}

修改后的回滚命令

将post阶段的回滚命令更新为:

runCmd("docker run -d -p 3002:3000 --restart unless-stopped --name ${env.DOCKER_CONTAINER_NAME} ${env.DOCKER_REPO}/${env.DOCKER_IMAGE_NAME}:latest")

问题2:容器移除失败导致新容器无法启动

问题原因

  • removeContainer函数中,runCmd使用returnStatus: true时返回的是命令退出状态码(0=成功,非0=失败),而非docker ps -q的输出内容,原判断逻辑将状态码当作容器存在标识,逻辑错误。
  • docker ps -q -f name=${containerName}仅检查运行中的容器,忽略已停止容器,导致停止状态的容器未被清理。

修复方案

  1. 调整容器存在性判断逻辑:通过状态码0判断容器存在
  2. 使用docker ps -a检查所有状态的容器(含已停止)
  3. 添加-f参数强制删除容器,确保清理彻底

修改后的removeContainer函数

def removeContainer(containerName) {
    // 检查所有状态的容器是否存在(包括已停止)
    def containerExists = runCmd("docker ps -a -q -f name=${containerName}")
    // 状态码为0表示容器存在
    if(containerExists == 0) {
        // 停止容器(如果运行中)
        runCmd("docker stop ${containerName}")
        // 强制移除容器
        runCmd("docker rm -f ${containerName}")
    }
}

完整优化后的流水线阶段代码

stage('Continuous deployment') {
    stages {
        stage('Build and Push Docker Image') {
            steps {
                echo 'Build and Pushing image...'
                script {
                    deployContainer(env.DOCKER_IMAGE_NAME)
                }
                echo 'Image pushed'
            }
        }
        stage('Run Docker Image') {
            steps {
                echo 'Running image...'
                script {
                    removeContainer(env.DOCKER_CONTAINER_NAME)
                    // 启动带构建号的新镜像
                    runCmd("docker run -d -p 3002:3000 --restart unless-stopped --name ${env.DOCKER_CONTAINER_NAME} ${env.DOCKER_REPO}/${env.DOCKER_IMAGE_NAME}:${env.BUILD_NUMBER}")
                }
                echo 'Running'
            }
            post {
                failure {
                    echo 'Rolling back to latest stable image...'
                    // 回滚前先清理残留容器
                    removeContainer(env.DOCKER_CONTAINER_NAME)
                    runCmd("docker run -d -p 3002:3000 --restart unless-stopped --name ${env.DOCKER_CONTAINER_NAME} ${env.DOCKER_REPO}/${env.DOCKER_IMAGE_NAME}:latest")
                }
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者Atram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 03:44:49