Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-38452

imageName() drops registry prefix outside of withRegistry() block

    • Icon: Bug Bug
    • Resolution: Not A Defect
    • Icon: Minor Minor
    • docker-workflow-plugin

      I have this pipeline:

      node {
           docker.withRegistry('https://my-private-repo') {
              sh 'echo "FROM ubuntu" > Dockerfile'
              img = docker.build('my-test-image:1.0.0')
              print img.imageName()
          }
          print img.imageName()
      }
      

      When the first print is done I get the expected full name with the registry prefix.
      The 2nd print however drops the registry prefix and I just get the id.

      Was not expecting that since the img object did not change.

          [JENKINS-38452] imageName() drops registry prefix outside of withRegistry() block

          Isn't this how it is supposed to work?

          Christian Höltje added a comment - Isn't this how it is supposed to work?

          Anthony Pioli added a comment -

          maybe?!?!

          But I was expecting the img object to retain it's full name.

          Anthony Pioli added a comment - maybe?!?! But I was expecting the img object to retain it's full name.

          But you went out of the .withRegistry() block. It wasn't there before and it isn't after the block.

          In fact, that code shouldn't work unless you had a def img before the withRegistry() block. Because the img variable should no longer exist outside.

          Christian Höltje added a comment - But you went out of the .withRegistry() block. It wasn't there before and it isn't after the block. In fact, that code shouldn't work unless you had a def img before the withRegistry() block. Because the img variable should no longer exist outside.

          docwhat but for me, it looks like it doesn't work even if you defy img inside withRegistry block - withRun still ignores the registry prefix in the name.

          Mikhail Sakhnov added a comment - docwhat but for me, it looks like it doesn't work even if you defy img inside withRegistry block - withRun still ignores the registry prefix in the name.

          Andrew Bayer added a comment -

          So first, the reason you're able to do anything with img when you reference it for the first time inside the withRegistry(...) block is that you defined it as img = ... - welcome to Groovy script variable scoping. =) If a variable is defined without a type or def ... in a Groovy script, it's global to the entire script. So for all intents and purposes, img = ... within the withRegistry(...) block works the same as def img before the withRegistry(...) block and then img = ... inside the block. However, if you did def img = ... inside the block, you would not be able to reference the img variable anywhere outside the block. Good times.

          Second, putting the Groovy scoping fun aside, yeah, this is expected behavior. withRegistry(...) alters behavior of Docker Pipeline methods/variables used inside its block, but only while you're in the block. So if you defined img before the withRegistry(...) block, img.imageName() called before the block wouldn't have the registry prefix, img.imageName() called inside the block would have the registry prefix, and img.imageName() called after the block wouldn't have the registry prefix. This is how this is supposed to work.

          Andrew Bayer added a comment - So first, the reason you're able to do anything with img when you reference it for the first time inside the withRegistry(...) block is that you defined it as img = ... - welcome to Groovy script variable scoping. =) If a variable is defined without a type or def ... in a Groovy script, it's global to the entire script. So for all intents and purposes, img = ... within the withRegistry(...) block works the same as def img before the withRegistry(...) block and then img = ... inside the block. However, if you did def img = ... inside the block, you would not be able to reference the img variable anywhere outside the block. Good times. Second, putting the Groovy scoping fun aside, yeah, this is expected behavior. withRegistry(...) alters behavior of Docker Pipeline methods/variables used inside its block, but only while you're in the block. So if you defined img before the withRegistry(...) block, img.imageName() called before the block wouldn't have the registry prefix, img.imageName() called inside the block would have the registry prefix, and img.imageName() called after the block wouldn't have the registry prefix. This is how this is supposed to work.

          Mikhail Sakhnov added a comment - - edited

          abayer proof me if I am wrong, but to me, it seems that there is no way to use an image from private registry now. Let me explain what I mean.

          img.pull command always uses ${imageName()} method (./main/resources/org/jenkinsci/plugins/docker/workflow/Docker.groovy:141) to build image name (so, inside withRegistry it would be with registry prefix, outside it would be without registry prefix)

          but img.withRun command instead of imageName uses directrly id property: 

          def container = docker.script.sh(script: "docker run -d${args != '' ? ' ' + args : ''} ${id}${command != '' ? ' ' + command : ''}", returnStdout: 
          true).trim()
          

          so if we pull some image inside some withRegistry block, it will save the image with the full qualified local name. But even if we call withRun inside the same withRegistry block, it would use the not full qualified name, but id property passed to image constructor.

          Pseudocode:

          docker.withRegistry("someregistry") {
              def image = docker.image("blablaimage")
              image.pull() // image saved to local docker with fq name 
              image.run() // tries to run blablaimage which doesn't exists because on previous step it was saved with fq name
          }
          

          Mikhail Sakhnov added a comment - - edited abayer proof me if I am wrong, but to me, it seems that there is no way to use an image from private registry now. Let me explain what I mean. img.pull command always uses ${imageName()} method (./main/resources/org/jenkinsci/plugins/docker/workflow/Docker.groovy:141) to build image name (so, inside withRegistry it would be with registry prefix, outside it would be without registry prefix) but img.withRun command instead of imageName uses directrly id property:  def container = docker.script.sh(script: "docker run -d${args != '' ? ' ' + args : ' '} ${id}${command != ' ' ? ' ' + command : ' '}" , returnStdout: true ).trim() so if we pull some image inside some withRegistry block, it will save the image with the full qualified local name. But even if we call withRun inside the same withRegistry block, it would use the not full qualified name, but id property passed to image constructor. Pseudocode: docker.withRegistry( "someregistry" ) { def image = docker.image( "blablaimage" ) image.pull() // image saved to local docker with fq name image.run() // tries to run blablaimage which doesn't exists because on previous step it was saved with fq name }

          Or may use case: Pull an image from one repository and publish it to another. You just can't do it without resorting to the shell.

          Christopher Bayliss added a comment - Or may use case: Pull an image from one repository and publish it to another. You just can't do it without resorting to the shell.

            Unassigned Unassigned
            apioli Anthony Pioli
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved: