Search code examples
dockerjenkinsjenkins-pipeline

How do I pull a Docker image from one private registry and push it to a second different private registry in Jenkins pipeline


I am able to connect to both private registries from Jenkins and I can pull the image I want to, however I don't know how to push that same image to a different repo.

Note, I am using scripted pipeline syntax since declarative syntax doesn't support pushing/pulling or custom registries as far as I know. I'm also not familiar with Groovy syntax.

Here's what I've got so far for my Jenkinsfile:

node {
    checkout scm

    docker.withRegistry('https://private-registry-1', 'credentials-1') {
        def image = docker.image('my-image:tag')
        image.pull()

        docker.withRegistry('https://private-registry-2', 'credentials-2') {
            image.push()
        }
    }
}

I put the second "withRegistry()" method within the first so that I could use the defined "image" variable.

I successfully connect to the first registry and pull the latest image. From Jenkins console output:

Login Succeeded
[Pipeline] {
[Pipeline] sh
+ docker pull private-registry-1/my-image:tag
tag: Pulling from my-image
Digest: sha256:XXXXX
Status: Image is up to date for private-registry-1/my-image:tag

However, here's the relevant error snippet after connecting to the second registry:

...
Login Succeeded
[Pipeline] {
[Pipeline] sh
+ docker tag my-image:tag private-registry-2/my-image:tag
Error response from daemon: No such image: my-image:tag
...

I am using a Jenkins container on my local Windows machine. It's connected to Docker for Windows through my Ubuntu terminal (Windows Subsystem for Linux).


Solution

  • The solution was to tag the image before pushing it, final code:

    node {
        checkout scm
    
        stage 'Pull latest image from private-registry-1'
    
        def image
        docker.withRegistry('https://private-registry-1', 'credentials-1') {
            image = docker.image('my-image:tag')
            image.pull()
        }
    
        stage 'Push image to private-registry-2'
    
        // SOLUTION START
        sh 'docker tag private-registry-1/my-image:tag private-registry-2/my-image:tag'
        image = docker.image('private-registry-2/my-image:tag')
        // SOLUTION END
    
        docker.withRegistry('https://private-registry-2', 'credentials-2') {
            image.push()
        }
    }
    

    I don't like how the tagging is done manually through "sh" but I couldn't find a way to do it through the built-in Docker syntax. I will also need to parameterize the image name and tag (my-image:tag) for future use.