I have a Jenkins pipeline that builds and runs a Docker machine, not as an agent, but using a scripting block along with the Docker Pipeline Plugin methods docker.build()
and Image.run()
. This works fine but if the build fails, the docker container is left running! I currently have Container.stop()
in a post{ always{} }
block but it doesn't seem to work. I don't want ssh into my Jenkins server to delete the container after every build and I can't just leave it because it has a specific and necessary name. How do I stop and rm the container regardless of failure of the build?
My pipeline:
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('[email protected]')
}
changed {
sendEmail('[email protected]')
}
}
}
Here is a working solution. You simply have to define a variable for the container outside the main pipeline. Then you can use it anywhere in the pipeline to start or stop the container. In particular, you can remove the container in 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('[email protected]')
}
changed {
sendEmail('[email protected]')
}
}
}
You can use Image.withRun() instead of Image.run().
Image.withRun[(args[, command])] {…}
Like run but stops the container as soon as its body exits, so you do not need a try-finally block.
Here other useful commands: https://qa.nuxeo.org/jenkins/pipeline-syntax/globals#docker
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With