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

Jenkins流水线Deploy阶段异常:容器运行于Jenkins容器而非目标EC2实例

问题描述

我使用如下Jenkins流水线:

pipeline {
    agent any 

    environment {
      UPLOADED_FILES_DIR='/tmp/spring_fileupload_dir'
      DOCKER_USR=credentials('docker_usr')
      DOCKER_PASSWD=credentials('docker_passwd')
    }

    stages {
        stage('Test') { 
            steps {
                sh 'mvn test' 
            }
        }

        stage('Package') { 
            steps {
                sh 'mvn clean package -Dmaven.test.skip=true' 
            }
        }

        stage('Build') { 
            steps {
                sh """
                    docker build -t azold6/fileupload-pv-pvc:$BUILD_NUMBER . 
                """ 
            }
        }

        stage('Push') { 
            steps {
                sh """
                    docker login -u="$DOCKER_USR" -p="$DOCKER_PASSWD"
                    docker push azold6/fileupload-pv-pvc:$BUILD_NUMBER
                """ 
            }
        }

        stage('Deploy') { 
            steps {
                sshagent(credentials : ['key-to-ec2']) {
                    sh "docker run -d --name fileupload --rm azold6/fileupload-pv-pvc:$BUILD_NUMBER"
                }
            }
        }
    }
}

执行到Deploy阶段时,抛出错误:

docker: Error response from daemon: Conflict. The container name "/fileupload" is already in use by container "d7c3ee093de7a06c90e71db1bfc85df849ee218da3ae0cf59aa0bd733d9501e2". You have to remove (or rename) that container to be able to reuse that name.

排查后发现,容器实际运行在Jenkins容器中,而非目标EC2实例,尽管用了SSH Agent插件,Jenkins还是指向了错误的机器。

解决方案

核心原因

sshagent插件仅负责加载SSH密钥,但当前的sh命令仍是在Jenkins代理节点(即Jenkins容器)本地执行,并未通过SSH连接到目标EC2实例。

具体修复方式

1. 修改Deploy阶段,通过SSH远程执行Docker命令

将本地docker run命令改为SSH连接EC2实例后执行的形式,示例代码:

stage('Deploy') { 
    steps {
        sshagent(credentials : ['key-to-ec2']) {
            sh """
                ssh -o StrictHostKeyChecking=no ec2-user@<你的EC2实例IP或域名> '
                    # 容错处理:停止并移除已存在的同名容器
                    docker stop fileupload || true
                    docker rm fileupload || true
                    # 拉取最新镜像并启动容器
                    docker pull azold6/fileupload-pv-pvc:$BUILD_NUMBER
                    docker run -d --name fileupload --rm azold6/fileupload-pv-pvc:$BUILD_NUMBER
                '
            """
        }
    }
}
  • 替换<你的EC2实例IP或域名>为实际的EC2地址
  • -o StrictHostKeyChecking=no用于避免首次连接时的主机密钥确认提示(生产环境可根据安全需求调整)
  • 增加docker stop和docker rm的容错命令,避免容器已存在导致的冲突

2. 确保EC2实例满足前置条件

  • EC2实例已安装Docker并启动服务
  • Jenkins代理节点(Jenkins容器)能通过指定的SSH密钥连接到EC2实例
  • EC2实例的操作用户(示例中为ec2-user)拥有Docker命令的执行权限(可通过将用户加入docker组实现)

3. 可选:使用SSH Pipeline Steps插件简化操作

若觉得手动编写SSH命令繁琐,可安装SSH Pipeline Steps插件,使用更简洁的语法:

stage('Deploy') { 
    steps {
        sshagent(credentials : ['key-to-ec2']) {
            script {
                def remote = [:]
                remote.name = 'EC2'
                remote.host = '<你的EC2实例IP或域名>'
                remote.user = 'ec2-user'
                remote.allowAnyHosts = true

                sshCommand remote: remote, command: '''
                    docker stop fileupload || true
                    docker rm fileupload || true
                    docker pull azold6/fileupload-pv-pvc:$BUILD_NUMBER
                    docker run -d --name fileupload --rm azold6/fileupload-pv-pvc:$BUILD_NUMBER
                '''
            }
        }
    }
}

该方式语法更清晰,也更便于维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 20:20:27