No such host error in Jenkins pipeline when pushing docker image to unauthorized private registry

I am trying to push a docker image to a private registry without any authentication configured. Below are how the jenkinsfile stages look like.

Without the writeFile command in the deploy stage I get no such host error

docker push <private-vm-name>:5000/temp/prototype-be:v1
The push refers to repository [<private-vm-name>:5000/temp/prototype-be]
Get https://<private-vm-name>:5000/v2/: dial tcp: lookup <private-vm-name> on 127.0.0.11:53: no such host

With the writeFile command I get an AccessDenied exception

java.nio.file.AccessDeniedException: /etc/docker

Could someone guide me on how could these errors be resolved in order to push to a private docker registry?

Thanks.

Jenkinsfile stages

        stage('Building docker image') {
            steps{
                script {
                    dockerImage = docker.build registry + ":v1"
                }
            }
        }

        stage('Pushing docker image') {
            steps{
                script {
                    writeFile file:"/etc/docker/daemon.json", text: "{
                            "insecure-registries": [
                               "<private-vm-name>:5000"
                            ]
                      }"
                    docker.withRegistry( 'http://<private-vm-name>:5000') {
                        dockerImage.push()
                    }
                }
            }
        }

Why don’t you setup that file before your job runs? That file can only be modified by root and you would need to restart docker for it to take effect.

Or better yet use letsencypt and give the repo a proper cert

Bare me for being new to jenkins. In my understanding jenkins server (which is running as a docker container) spaws a new container everytime it executes a jenkins pipeline script.

Why don’t you setup that file before your job runs? That file can only be modified by root and you would need to restart docker for it to take effect.

How do I setup the file in the docker container that is spawned by jenkins server?

better yet use letsencypt and give the repo a proper cert

By repo did you mean the git repo? I didn’t catch how is it related to it. In my earlier build stage of the pipeline I have a docker image created. I need to now push it to a private docker repository.

That’ll greatly depend on your setup. There’s no one way to do it. In your case it really only matters where the docker dameon is running. I can’t really answer it for you, but often people will run docker on the outside, and mount the docker socket inside the jenkins controller container. I really don’t know how to suggest finding the daemon. Do you know how the thing was setup? was it a dind (docker inside of docker) setup?

Run a container you control.

It’s easy to extend images.

FROM node:14
RUN do thing that extends image

That being said, docker daemon doesn’t run in those images, so you’ll want to update it earlier than that.

No i mean the docker registry your pushing to.

your doing HTTP://, and trying to tell daemon.json to accept that the registry (private-vm-name) isn’t https. Another solution is just to be https :slight_smile:

Yes I am using dind. For starting the jenkins server on vm I execute these 3 commands which
includes the dind docker container.

docker network create jenkins

  docker run --name jenkins-dind --detach \
  --privileged --network jenkins --network-alias docker \
  --env DOCKER_TLS_CERTDIR=/certs \
  --volume jenkins-docker-certs:/certs/client \
  --volume jenkins_home:/var/jenkins_home \
  --restart unless-stopped \
  --publish 2376:2376 docker:dind --storage-driver overlay2

  docker run --name jenkins --detach -p 49999:8080 -p 50000:50000 \
  --cpus="1.0" --memory="2g" \
  --network jenkins --env DOCKER_HOST=tcp://docker:2376 \
  --env DOCKER_CERT_PATH=/certs/client --env DOCKER_TLS_VERIFY=1 \
  -v jenkins_home:/var/jenkins_home \
  -v jenkins-docker-certs:/certs/client:ro \
  --restart unless-stopped \
  --env JENKINS_OPTS="--prefix=/jenkins" 4oh4/jenkins-docker

I do not want to configure https for my docker registry since its private :slight_smile: .

As I am troubleshooting further, I think the problem is the docker container spawned by jenkins server to execute the pipeline cannot connect with the docker registery container running on the same machine even though port 5000 is exposed by the docker registry container (I verified that by executing curl -X GET http://vm-name:5000/v2/_catalog from another vm).

When I execute curl -X GET http://vm-name:5000/v2/_catalog or curl -X GET http://localhost:5000/v2/_catalog from the jenkins pipeline script through sh I get errors Could not resolve host: <vm-name> and Failed to connect to localhost port 5000: Connection refused respectively.

What changes do I need to allow the jenkins pipeline docker container spawned at runtime by the server make api calls to the registry docker container running on the same vm?

Thanks.

just to be clear, jenkins doesn’t span that docker server.

Is your registry running on that server as well? You can either --link it which might work, I’m not sure you can link across networks. Or use the non internal IP for the external host.

Sadly this is kinda a bigger docker question, and while I know how to do it myself, I don’t know if I know how to explain it properly. Docker Tip - How to use the host's IP Address inside a Docker container on macOS, Windows, and Linux - DEV Community sorta tells you what you can do? but its different between linux and mac/windows.

I can’t find it in the docs, but you’ll want to mount a daemon.json when you startup the dind image with -v so its present when its started.

just to be clear, jenkins doesn’t span that docker server.

Do you mean jenkins server does not spawn a docker container for executing the pipeline? If so, how does the pipeline execute - directly inside the jenkins docker container?

Is your registry running on that server as well?

That’s right. The docker registry (container) is running on the same server as jenkins.

you’ll want to mount a daemon.json when you startup the dind image with -v so its present when its started.

Ok. Will check on this further.

I’ve been fighting a migraine all day so my words haven’t been that well thought out, my apologies. I’m saying the jenkins server doesn’t manage the docker server. It does however tell the docker server to tell it to spin up container sand talk to it.

Right. So the problem is the docker pipeline container cannot access the docker registry container. It is getting the errors I reported above.

While troubleshooting this issue I tried to connect to the docker registry container with a test ubuntu container. The curl failed with the same error. On editing the /etc/hosts file I could get the curl command running.

How do I edit the /etc/hosts file in the spawned jenkins pipeline docker container to add the name of the vm and its ip address?

On making further progress on this troubleshooting I tried specifying the ip address of the server instead of the vm name so that I don’t need to edit /etc/hosts file but then I get an error because the daemon.json file is missing (which is what I reported above)

+ docker push 172.27.56.26:5000/temp/prototype-be:v1
The push refers to repository [172.27.56.26:5000/temp/prototype-be]
Get https://172.27.56.26:5000/v2/: http: server gave HTTP response to HTTPS client

I tried creating a custom docker dind image by following this stackoverflow post but that didn’t help. I get the same error as above

I could get this working by modifying the docker run for docker:dind with --insecure-registry <ip>:5000 parameter