Selenium Docker Integration Through Jenkinsfile – Managing Local Docker Registry

Overview:

We already have seen few articles on Selenium Docker Integration Through Jenkinsfile series. If you have not read the Part 1 to 3, I would request you to check below.

In the part 2 of the series, We were using DockerHub to share our docker images. It is easy to use DockerHub. It is also available in public internet. This could either be an advantage or a disadvantage depends on your requirements.

That is, anyone with internet could download the image you have pushed and try to access your project files. DockerHub also provides an option – private docker registry for a small fee. You could go with that option. Or You can try to have your own docker registry within your office network for free! Lets see how it can be done in this article.

Udemy – Selenium WebDriver With Docker:

TestAutomationGuru has released a brand new course in Udemy on Selenium WebDriver with Docker. 14 hours course which starts with installing docker from scratch and goes all the way up to running dockerized selenium tests on AWS cloud. Please access the above link which gives you the special discount.  You can also get your money back if you do not like the course within 30 days.

Prerequisite:

  • You already have gone through above 3 articles
  • You have a machine with below software installed
    • docker
    • docker-compose

Local Repository Setup:

The local docker registry setup is very easy. In fact it can be done using below docker-compose file with a single command.

  • Create a separate directory
  • Copy the below content and place it in a file – docker-compose.yaml
version: "3"
services:
  registry:
    image: registry:2
    restart: always
    container_name: registry
    ports:
      - "5000:5000"
    volumes:
      - ./myrepo:/var/lib/registry
  registry-ui:
    image: joxit/docker-registry-ui:static
    container_name: registry-ui
    restart: always
    ports:
      - "80:80"    
    depends_on:
      - registry
    environment:
      - REGISTRY_URL=http://registry:5000
      - DELETE_IMAGES=true
      - REGISTRY_TITLE=TestAutomationGuru

The above yaml file has 2 services.

  • registry
    • This is the container which acts like our DockerHub in local / within our network.
    • This container exposes APIs at port 5000 for pushing / pulling docker images.
    • We need to store the docker images in some location. So we keep them in the myrepo directory and map them to /var/lib/registry.
  • registry-ui
    • The above registry service exposes only REST API. Does not provide any UI. So, This service provides an UI for the registry service.
    • We need to set this REGISTRY_URL = http://registry:5000 as registry-ui container can access registry container at port 5000 using the default network created by docker.
    • The other 2 environment variables are optional.

Issue the below command to start the docker registry.

sudo docker-compose up -d

At this point, you should be able to access http://localhost and you should see something like this.

Screenshot from 2018-12-31 15-53-25

We have our own docker registry now!

Docker Registry With HTTP:

Even though we have created a docker registry, by default docker lets you push the docker image only within local. That is you can build an image in the machine & push the image you have built where you are running the above docker registry. You can not access push/pull an image from another machine within the same network. This is the default behavior. Because docker does not encourage HTTP protocol. It requests us to use HTTPS instead.

No worries! We have work around.

As we are in our office network, we assume that it is safe to use HTTP within your organization network. We are not exposing our docker registry outside the office network.

Do the below changes in each machine which might pull / push images from/into the docker registry.

  • Create a json file under /etc/docker/daemon.json
  • Place the below json file. Here we give our docker-registry path Ip-address : port (10.11.12.13 is the IP address of the machine in my case which is running docker registry service)
{
   "insecure-registries":[
      "10.11.12.13:5000"
   ]
}
  • Restart docker daemon

Screenshot from 2018-12-31 16-36-46

Now each machine in the network is ready to use our Docker-registry.

Pushing to Docker Repository:

If you remember the process we followed to push the docker images to docker hub, then this process is exactly same. Check the ‘Push Image’ section in the below pipeline. We changed our docker registry URL instead of DockerHub. Everything else remains same.

pipeline {
    agent {
        node {
            label 'docker' && 'maven'
        }
    }
    stages {    
        stage('Build Jar') {
            steps {
                sh 'mvn clean package -DskipTests'
            }
        }
        stage('Build Image') {
            steps {
                      app = docker.build("vinsdocker/containertest")
                }
            }
        }
        stage('Push Image') {
            steps {
                script {
                    // http://10.11.12.13:5000 is our docker registry
                    docker.withRegistry('http://10.11.12.13:5000') {
                        app.push("${BUILD_NUMBER}")
                        app.push("latest")
                    }
                }
            }
        }        
    }
}

Running the Jenkins job should be able to push our docker image into our docker registry as shown here. You could access the UI at port 80 and see more details about the image.

Screenshot from 2018-12-31 17-08-23

Pulling From Docker Registry:

As you know, in the docker image –  vinsdocker/containertest

  • vinsdocker – is the name of our docker account or our organization name.
  • containertest – is the name of our docker image which contains the selenium test.

By default, when you try to pull, docker looks for such image in the DockerHub. We can request docker to look for images in our docker hub by appending the registry url as shown below.

10.11.12.13:5000/vinsdocker/containertest

For ex: below command will pull the image from my docker registry.

docker pull 10.11.12.13:5000/vinsdocker/containertest

Running Our Selenium Tests Using Jenkins:

Now instead of referring to dockerhub, we update the pipeline script to look for our docker registry.

  • Check the Run Test section for the update I have done.
  • Do note that we are NOT updating for selenium grid. Because those images are not part of our docker registry. So docker has to pull those images from docker hub.
pipeline {
  
   agent { label 'docker' }

   stages{
      stage('Setting Up Selenium Grid') {
         steps{        
            sh "docker network create ${network}"
            sh "docker run -d -p 4444:4444 --name ${seleniumHub} --network ${network} selenium/hub"
            sh "docker run -d -e HUB_PORT_4444_TCP_ADDR=${seleniumHub} -e HUB_PORT_4444_TCP_PORT=4444 --network ${network} --name ${chrome} selenium/node-chrome"
            sh "docker run -d -e HUB_PORT_4444_TCP_ADDR=${seleniumHub} -e HUB_PORT_4444_TCP_PORT=4444 --network ${network} --name ${firefox} selenium/node-firefox"
         }
      }
      stage('Run Test') {
         steps{
            parallel(
               "search-module":{
                  sh "docker run --rm -e SELENIUM_HUB=${seleniumHub} -e BROWSER=firefox -e MODULE=search-module.xml -v ${WORKSPACE}/search:/usr/share/tag/test-output --network ${network} 10.11.12.13:500/vinsdocker/containertest"
                  archiveArtifacts artifacts: 'search/**', fingerprint: true
               },
               "order-module":{
                  sh "docker run --rm -e SELENIUM_HUB=${seleniumHub} -e BROWSER=chrome -e MODULE=order-module.xml -v ${WORKSPACE}/order:/usr/share/tag/test-output  --network ${network} 10.11.12.13:500/vinsdocker/containertest"
                  archiveArtifacts artifacts: 'order/**', fingerprint: true
               }               
            ) 
         }
      }
    }
    post{
      always {
         sh "docker rm -vf ${chrome}"
         sh "docker rm -vf ${firefox}"
         sh "docker rm -vf ${seleniumHub}"
         sh "docker network rm ${network}"
      }   
   }
}

Now, Jenkins is able to set up selenium grid using the images available in DockerHub and run the test by pulling the image from our docker registry.

Summary:

We were able to successfully start the selenium grid, running our test inside containers and terminate them all at run time. By creating a local docker registry within our office network, we keep our docker image safe. By using Jenkinsfile, we are able to document the complete build information in a text file and reuse. We were also able to run multiple test suites in parallel using Jenkinsfile.

Happy Testing & Subscribe 🙂

 

 

Share This:

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.