【问题标题】:What is the proper way to stop and remove a docker container in Jenkins when using Docker Pipeline Plugin?使用 Docker Pipeline Plugin 时,在 Jenkins 中停止和删除 docker 容器的正确方法是什么?
【发布时间】:2018-05-05 05:22:48
【问题描述】:

我有一个构建和运行 Docker 机器的 Jenkins 管道,它不是作为代理,而是使用脚本块以及 Docker 管道插件方法 docker.build()Image.run()。这工作正常,但如果构建失败,docker 容器将继续运行!我目前在post{ always{} } 块中有Container.stop(),但它似乎不起作用。我不希望 ssh 进入我的 Jenkins 服务器以在每次构建后删除容器,我不能只留下它,因为它有一个特定且必要的名称。 无论构建失败,我如何停止和 rm 容器?

我的管道:

pipeline {
    agent none
    stages {
        stage('Checkout') {
            agent any
            steps {
                checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '<some credentials>', url: '<a git repo>']]])
            }
        }
        stage('Spin Up Receiver') {
            agent any
            steps {
                script { 
                    def receiver = docker.build("receiver",  "--rm centos7_receiver")
                    def receiver_container = receiver.run("-d -v ${PWD}/realtime_files/station_name/201707/f/20170710_191:/DSK1/SSN/LOG0_f/17001 --network='rsync_test' --name='test_receiver'")
                }
            }
        }
        stage('Run Tests') {
            agent { dockerfile { args '-v /etc/passwd:/etc/passwd --network="rsync_test"' } }
            steps {
                sh "python ./rsyncUnitTests.py"
            }
        }
    }
    post {
        always {
            script { 
                receiver_container.stop()
            }
        }
        failure {
            sendEmail('foo@bar.com')
        }
        changed {
            sendEmail('foo@bar.com')
        }
    }
}

【问题讨论】:

  • 我找到了答案。您必须为 pipeline 的 docker 机器 outside 声明变量 (def receiver_container)。然后你可以从管道中的任何地方调用它,它会被识别。
  • 您能否提供您的解决方案来回答您自己的问题?

标签: docker jenkins-plugins jenkins-pipeline


【解决方案1】:

这是一个可行的解决方案。您只需为主管道外部的容器定义一个变量。然后,您可以在管道中的任何位置使用它来启动或停止容器。特别是,您可以删除post{ always{ } }中的容器。

def receiver_container
pipeline {
    agent any
    stages {
        stage('Checkout') {
            agent any
            steps {
                checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '<some credentials>', url: '<a git repo>']]])
            }
        }
        stage('Spin Up Receiver') {
            agent any
            steps {
                script { 
                    def receiver = docker.build("receiver",  "--rm receiver_docker")
                    receiver_container = receiver.run("-d -u 0:0 -v /var/lib/jenkins/workspace/RsyncRealtime/jenkins_rt:/DSK1/SSN/LOG5_F/17191 --network='rsync_test' --name='test_receiver'")
                }
            }
        }
        stage('Run Unit Tests') {
            agent { 
                dockerfile { 
                    args '-u 0:0 -v /etc/passwd:/etc/passwd --network="rsync_test"'
                } 
            }
            steps {
                sh "sshpass -p 'test' ssh anonymous@test_receiver ls -l /DSK1/SSN/LOG5_F/17191"
                sh "python ./rsyncUnitTests.py"
            }
        }
    }
    post {
        always {
            script { 
                receiver_container.stop()
            }
        }
        failure {
            sendEmail('foo@bar.com')
        }
        changed {
            sendEmail('foo@bar.com')
        }
    }
}

【讨论】:

  • 这确实有效并且已经过验证,但我认为@PlinioSilveira 的答案更简洁。
【解决方案2】:

您可以使用 Image.withRun() 代替 Image.run()。

Image.withRun[(args[, command])] {…}

与 run 类似,但在容器主体退出后立即停止容器,因此您不需要 try-finally 块。

这里还有其他有用的命令: https://qa.nuxeo.org/jenkins/pipeline-syntax/globals#docker

【讨论】:

  • 另外,Image.inside[(args)] {…} 允许完成整个命令块,然后在完成后移除容器。
  • 但是之后会不会也删除容器?
  • 当使用inside{}时,我得到了日志$ docker rm -f 8f10dc0b3e,所以我相信它会在之后删除容器。
猜你喜欢
  • 1970-01-01
  • 2020-10-18
  • 2019-08-28
  • 2022-08-03
  • 2019-08-11
  • 1970-01-01
  • 2016-03-17
  • 1970-01-01
  • 2019-03-04
相关资源
最近更新 更多