23
votes

I'm new to using Jenkins....

I'm trying to automate the production of an image (to be stashed in a repo) using a declarative Jenkinsfile. I find the documentation to be confusing (at best). Simply put, how can I convert the following scripted example (from the docs)

node {
    checkout scm
    def customImage = docker.build("my-image:${env.BUILD_ID}")
    customImage.push()
}

to a declarative Jenkinsfile....

3
The question is, of course, a specific example of the more generic question - How do I use the Docker Pipeline features in general from a declarative Jenkinsfile?MarkH
YES the documentation is a horrid jumble of new declarative and old scripted syntax, even three years after this question was asked. The lack of useful SO answers and doc contributors makes me suspect the Jenkins pipeline community is small, could that be?chrisinmtown

3 Answers

34
votes

You can use scripted pipeline blocks in a declarative pipeline as a workaround

pipeline {
    agent any
    stages {
        stage('Build image') {
            steps {
                echo 'Starting to build docker image'

                script {
                    def customImage = docker.build("my-image:${env.BUILD_ID}")
                    customImage.push()
                }
            }
        }
    }
}
8
votes

I'm using following approach:

steps {
   withDockerRegistry([ credentialsId: "<CREDENTIALS_ID>", url: "<PRIVATE_REGISTRY_URL>" ]) {
      // following commands will be executed within logged docker registry
      sh 'docker push <image>'
   }
}

Where:

  • CREDENTIALS_ID stands for key in Jenkis under which you store credentials to your docker registry.
  • PRIVATE_REGISTRY_URL stands for url of your private docker registry. If you are using docker hub then it should be empty.
0
votes

First a detail about the scm step: when I defined a Jenkins "Pipeline script from SCM" project that fetches my Jenkinsfile from my git repo, and that Jenkinsfile contains a declarative pipline, Jenkins cloned the repo as the first step in the pipeline even tho I did not define a scm step.

For the build and push steps, I can only find solutions that are a hybrid of old-style scripted pipeline steps inside the new-style declarative syntax. For example see gustavoapolinario's work at Medium:

https://medium.com/@gustavo.guss/jenkins-building-docker-image-and-sending-to-registry-64b84ea45ee9

which has this hybrid pipeline definition:

pipeline {
  environment {
    registry = "gustavoapolinario/docker-test"
    registryCredential = 'dockerhub'
    dockerImage = ''
  }
  agent any
  stages {
    stage('Cloning Git') {
      steps {
        git 'https://github.com/gustavoapolinario/microservices-node-example-todo-frontend.git'
      }
    }
    stage('Building image') {
      steps{
        script {
          dockerImage = docker.build registry + ":$BUILD_NUMBER"
        }
      }
    }
    stage('Deploy Image') {
      steps{
        script {
          docker.withRegistry( '', registryCredential ) {
            dockerImage.push()
          }
        }
      }
    }
    stage('Remove Unused docker image') {
      steps{
        sh "docker rmi $registry:$BUILD_NUMBER"
      }
    }
  }
}

Because the first step here is a clone, I think he built this example as a standalone pipeline project in Jenkins.

Anyhow I'm hard pressed to justify using the new declarative syntax bcos it seems that every important step requires falling back to the old scripting syntax.