Jenkins with Remote Docker machine

Sometimes there will be cases where we have to execute in a remote machine. So the same case will be applicable for a Jenkins execution also. When we configure a job in Jenkins, we might need to run that particular content in another virtual machine or a remote machine.

In such cases, we have to establish a connection to the remote machine from Jenkins to execute the content.

When an organization has more virtual machines, it becomes easier to connect with them and work, but in some organizations, they will have the limitation for the virtual machines.

In such cases, we will be using a docker to create a virtual machine and will connect to that particular docker container and execute our Jenkins job.

I hope you know that the docker container is nothing but a basic version of a Unix system or it could be any other OS system.

So let me explain my case here, I have a Windows laptop, now I have created a virtual machine with Virtualbox, and my virtual machine is centos 8.

In the centos I have installed the docker, I have created one of the docker containers to contain Jenkins; similarly, I have created another docker container that will have a remote machine where scripts will be executed from Jenkins.

So in this lecture, we are going to learn how to execute a Jenkins job in a remote Docker container.

Create a new Virtual machine with docker

  • Create a folder according to the OS you are about to create; am creating centos-vm, I have created the folder in the same directory as where docker-compse.yml is present.
    [[email protected] jenkins-data]# ls
    demo.sh  docker-compose.yml  jenkins_home
    [[email protected] jenkins-data]# mkdir centos-vm
    [[email protected] jenkins-data]# ls
    centos-vm  demo.sh  docker-compose.yml  jenkins_home
  • Navigate inside the newly created directory
    cd centos-vm/​
  • Create a Docker file for creating a docker image, which acts as our virtual machine.
    vi Dockerfile​

Dockerfile content:

  • What OS we want to install (centos and version 7)
    FROM centos​:7
  • RUN command executes the given command in docker; Install an ssh server in the VM
    RUN yum -y install openssh-server​
  • Create a User and password; also create a directory where we can store or Password related stuff for further connections. We are Setting permission that only remote_user to read and write that password-related directory.
    RUN useradd remote_user && 
        echo "1234" | passwd remote_user  --stdin && 
        mkdir /home/remote_user/.ssh && 
        chmod 700 /home/remote_user/.ssh
  • echo "remote_user:1234" | chpasswd sets the password for the created user.
  • In the above steps, we are setting the user name and password while creating VM; it will be easier for Jenkins to connect to a virtual machine if we make the authorization keys.
  • Save the above-created file and exit the editor;
  • Generate a key; I left password fields empty
    ssh-keygen -f remote-key​

    remote-keys-jenkins-docker

  • list the directory
    [[email protected] centos-vm]# ls
    Dockerfile  remote-key  remote-key.pub​
  • remote-key is a private key and remote-key.pub is a public key
  • Edit the Dockerfile and COPY the remote-key.pub file into the virtual machine.
    COPY remote-key.pub /home/remote_user/.ssh/keys​
  • Change the ownership of the keys folder; now remote_user only has ownership from remote_user group
    #chown username:groupname -R directory
    RUN chown remote_user:remote_user -R​ /home/remote_user
  • Change the permissions to 600 for the keys folder
    chmod 600 /home/remote_user/.ssh/keys​
  • Create global keygen for the ssh server in the virtual machine (for centos 8; it will differ for other versions)
    RUN /usr/sbin/sshd-keygen
  • Set how the ssh service should be started and Save the file
    CMD /usr/sbin/sshd -D​

Complete Dockerfile content

FROM centos:7

RUN yum -y install openssh-server

RUN useradd remote_user && 
    echo "1234" | passwd remote_user  --stdin && 
    mkdir /home/remote_user/.ssh && 
    chmod 700 /home/remote_user/.ssh

COPY remote-key.pub /home/remote_user/.ssh/authorized_keys

RUN chown remote_user:remote_user   -R /home/remote_user && 
    chmod 600 /home/remote_user/.ssh/authorized_keys

RUN /usr/sbin/sshd-keygen

CMD /usr/sbin/sshd -D

Add service to docker-compose.yml

So far, we have set the details of how the virtual machine should be. Now we have to edit the docker-compose file to create an image using the Dockerfile we created.

  • Go back to the folder where you have the docker-compose.yml
    [[email protected] centos-vm]# ls
    Dockerfile  remote-key  remote-key.pub
    [[email protected] centos-vm]# cd ..
    [[email protected] jenkins-data]# ls
    centos-vm  demo.sh  docker-compose.yml  jenkins_home​
  • Edit the docker-compose.yml file add another service (virtual machine creation)
    remote_vm:
        container_name: remote_vm
        image: remote_vm
        build:
          context: centos-vm
        networks:
          - net​
  • remote_vm : is the service name
  • container_name : the docker name, using which we can log into the bash
  • image : name for the image
  • build: where the Dockerfile related things present; directory path where the Dockerfile is present
  • networks: which network the docker image should be using. Make sure that Jenkins network and this network match, otherwise you cannot connect Jenkins to the virtual machine.

Complete docker-compose.yml file

version: '3.7'
services:
  jenkins:
    container_name: jenkins
    image: jenkins/jenkins
    ports:
      - "8080:8080"
    volumes:
      - $PWD/jenkins_home:/var/jenkins_home
    networks:
      - net

  remote_vm:
    container_name: remote_vm
    image: remote_vm
    build:
      context: centos-vm
    networks:
      - net
networks:
  net:
Build the image:

Now we are done with configurations; let's build the image for the virtual machine.

docker-compose build

docker-compse-build-jenkins

Verify whether the centos image has been downloaded.

docker images

docker-images-centos-download-jenkins

From the above image, you can confirm that centos and remote_vm images are present/downloaded.

Bring virtual machine Up:

In the above command, you have built the virtual machine, but that does not mean you have made the service up.

Let's make the virtual machine up using the docker-compose

docker-compose up -d

docker-compose-up-remote-machine

Verify whether the virtual machine is up.

docker ps

virual-machine-up-jenkins

Connect to Virtual machine:

You cannot connect to the virtual machine from the base machine (where all images are present) because the base machine and virtual machine are not in the same network

ssh [email protected]_vm

connect-vm-remote-machine

The Jenkins machine can connect to the virtual machine because they are in the same network (-net). Check docker-compose.yml if you have doubts.
jekins-remote-machine-connection

So if you provide the password you will able to log in, and the password we have set is "1234". But every time we try to login, it will ask for the password, to avoid this we have already created remote-key and remote-key.pub

Also, we have already copied the remote-key.pub to the virtual machine using the Dockerfile

COPY remote-key.pub /home/remote_user/.ssh/authorized_keys

Now we have to copy the remote-key file to the Jenkins container so that we can log in without providing the password.

The copy command for docker docker cp remote-key jenkins:/tmp/

[[email protected] jenkins-data]# cd centos-vm/
[[email protected] centos-vm]# ls
Dockerfile  remote-key  remote-key.pub
[[email protected] centos-vm]# docker cp remote-key jenkins:/tmp/

Before you can use the remote key, change the permission for the remote key.

docker exec -u root jenkins bash -c "chown jenkins:jenkins /tmp/remote-key"

Now try to login from Jenkins container; -i /tmp/remote-key used to mention where the key is present.

ssh -i /tmp/remote-key [email protected]_vm

using-remote-key-ssh-jenkins

Install SSH plugin to Jenkins

We have to add SSH plugins to connect with a remote server in Jenkins;

  • Click Manage Jenkins > Select Manage Plugins

    manage-plugins-jenkins
  • Go to Available Tab
    avilable-plugins-jenkins-ssh
  • Search For SSH
    ssh-plugin-jenkins
  • Select the checkbox and click Install Without restart button
  • Your Plugin will be install and No need to restart
    ssh-installed-jenkins
  • Go to the dashboard and select the Credential link.
    credential-jenkins-ssh
  • Click on the Jenkins link.
    score-jenkins-password-global
  • Select Add credentials
    add-credential-jenkins
  • Select SSH user and with the private key
    ssh-username-private-key-jenkins
  • Copy the content of remote-key from the machine
    remote-key-jenkins

  • Paste the copied value in the private key field
    private-key-jenkins-username-id
  • Press the Ok button to save the details, and you will see the details.
    id-credential-jenkins
  • Go back to the Dashboard and Select manage Jenkins.
    configure-jenkins-ssh
  • Select Configure System
    configure-system-jenkins
  • Scroll down to SSH remote Hosts and click on Add button
    ssh-remote-hosts-jenkins
  • Enter the details of the host and select the credential
    ssh-remote-hosts-jenkins-creds
  • After select details click on check connection button to ensure the connection
    connections-successful
  • Create a New Job with Freestyle ( job name =Remote Execution)
  • Scroll down to build step and Add Build steps as Execute shell script on the remote host using ssh
    build-step-jenkins
  • Add below shell command and choose the credential.
    echo "this is from jenkins" >  /tmp/demo-remote-execution.txt​

    demo-remote-execution-jenkins
  • We are trying to create a file called demo-remote-execution.txt and place "this is from jenkins" text in it.
  • Save and Build the job; Go to the build number and see the console output.
    console-output-jenkins-remote-execution
  • Now let's go the remote_vm virtual machine and check the file.
    [[email protected] jenkins-data]# ls
    centos-vm  demo.sh  docker-compose.yml  jenkins_home
    [[email protected] jenkins-data]# docker exec -it remote_vm bash
    [[email protected] /]# cat /tmp/demo-remote-execution.txt
    this is from jenkins​

    remote-file-saved-jenkins
About Author :

I am Pavankumar, Having 8.5 years of experience currently working in Video/Live Analytics project.

Comment / Suggestion Section
Point our Mistakes and Post Your Suggestions