Jenkins

Created: Jenkins Setup Guide and General Information

Updated: 03 September 2023

The Guide for getting started can be found here

Setup

Prerequisites

  1. Docker
  2. Java 8
  3. Download Jenkins here

Place your jenkins.war file in the project root directory

Running

Run jenkins with the following command from the project root

Terminal window
1
java -jar jenkins.war --httpPort=8080

Navigate to http://localhost:8080 in your browser and complete the setup

You may need to configure the proxy, do this using the version without the http:// part - for some reason it doesn’t work otherwise. The Jenkins install will be at C:\Users\USERNAME\.jenkins

You can find the Admin Password at C:\Users\USERNAME\.jenkins\secrets\initialAdminPassword

Adding a Local Repo

We can add a local repository by simply linking to it with file://C:/Users/USERNAME/source/repos/jenkins-getting-started

Setting Up a Build

I’m using the BlueOcean Plugin to build the pipellines as the visual editor is easier, the documentation on using that can be found here

When configuring the pipeline on BlueOcean, you may run into an error when running a bash script on a Windows host, use Powershell Instead

Docker Registry

Creating a local docker registry to store applications can be done by simply running the registry container, and then adding stage after the build to push the content to that registry and then run that as opposed to the “local” version of the container

Start a local registry with

Terminal window
1
docker run -d -p 5000:5000 --restart=always --name registry registry:2

We will push the content to the Docker Registry using the following command

Terminal window
1
docker push localhost:5000/node-hello-world

If having issues with the above use 127.0.0.1:5000 instead of localhost:5000

The image can be removed from the build server with

Terminal window
1
docker image remove 127.0.0.1:5000/node-hello-world

Stop current running application and clean environment on target machine

Terminal window
1
docker stop node-app
2
docker container prune -f

Note that with the above you need to be sure to check if there is a container with that name currently running or else it will throw an error. This is handled using the following script in the pipeline:

Terminal window
1
if (((docker container ls) | Out-String).Contains('node-app')) { docker container stop node-app; echo "Application Stopped" } else {echo "Application not running"} docker container prune -f

The final Docker image will be run on the client with

Terminal window
1
docker run -d -p 3001:3000 --name node-app 127.0.0.1:5000/node-hello-world

Build Kickoff Automation

Ensure your git proxy is set up correctly with:

Terminal window
1
git config --global http.proxy ....

You need to make use of a post-commit hook in your .git/hooks/post-commit file with the following content, note that you need to make sure to bypass the proxy

1
#!/bin/sh
2
curl --proxy "" --location http://localhost:8080/git/notifyCommit?url=file://C:/Users/USER/source/repos/jenkins-getting-started

Running a Build Slave

Ther are multiple methods for configuring a Jenkins Build Slave, usually using JNLP or SSH

You can run a slave instance for JNLP with docker using:

1
docker run jenkins/jnlp-slave -url http://jenkins-server:80 agentSecret jnlp-slave

Or an SSH Slave with:

1
docker run -p 22:22 jenkinsci/ssh-slave YOURPASSPHRASE

You will need to get your SSH key from the slave though, you can do this with:

1
ssh-keygen -t rsa

DIY Docker SSH Build Slave

This is probably not a good idea but it works fine for testing your connections

First create the sshUbuntu.Dockerfile so we have something to run

1
FROM ubuntu:16.04
2
3
RUN apt-get update
4
RUN apt-get install -y openssh-server
5
RUN apt-get install -y default-jdk
6
7
RUN mkdir /var/run/sshd
8
RUN echo 'root:YOURPASSKEY123' | chpasswd
9
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
10
11
# SSH login fix. Otherwise user is kicked off after login
12
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
13
14
ENV NOTVISIBLE "in users profile"
15
RUN echo "export VISIBLE=now" >> /etc/profile
16
17
# if not already created
18
WORKDIR /root
19
RUN mkdir .ssh
20
WORKDIR /root/.ssh
21
22
# # when generating the key you can just leave the passphrase blank
23
RUN ssh-keygen -t rsa -f for_jenkins_key -N ""
24
25
# # add the jenkins key to the authorized keys
26
RUN cat for_jenkins_key.pub > authorized_keys
27
RUN cat authorized_keys
28
29
# # print out and copy the private `for_jenkins_key` file contents to the Jenkins Setup - not the `.pub`
30
RUN cat for_jenkins_key
31
32
WORKDIR /
33
EXPOSE 22
34
CMD ["/usr/sbin/sshd", "-D"]

And then build and run that image with:

1
docker build -t ssh-ubuntu -f sshUbuntu.Dockerfile .
2
docker run -d -p 22:22 ssh-ubuntu

You can then log into this instance using SSH to test the connection (this is built into bash on Windows)

Terminal window
1
# clear existing keys for the host
2
# ssh-keygen -R yourhostname
3
ssh-keygen -R localhost
4
5
ssh roo@localhost
6
7
> password : YOURPASSKEY123
8
9
# check the generated key with:
10
cd ~/.ssh
11
cat for_jenkins_key
12
13
# after you have tested the SSH connection you can disconnect with
14
exit

Then copy the entire key from the previous script and move to your Jenkins Setup

Jenkins Slave Config

Credentials

First go to your Jenkins Instance and Navigate to Jenkins > Credentials > System > Global or the following route in your browser /credentials/store/system/domain/_/

And click Add Credential, select the type as SSH Username with private key and set the username as root (or your actual user if you’re doing this for real) and Select Private Key: Enter Directly and paste in the Key you copied from your slave container instance, if you created a Passphase for the key (the Docker one above does not) you will need to enter that in as well

Node

Then navigate to Jenkins > Manage > Manage Nodes or /computer/ in your browser and click New Node. Give this a name, e.g. ubuntudockerssh, use the Permanent Agent option. Thereafter set the Launch Method to be Launch Agents via SSH , the host should be localhost or whatever your actual host is, and be sure to use the Credentials we just created. Lastly the Host Key Verification Strategy should be Manually Trusted key verification strategy and click save

Test Build

A simple Pipeline can be built using the following. Note that the agent.label value is the name of the Node set up in the previous step

1
pipeline {
2
agent {label 'ubuntudockerssh'}
3
stages {
4
stage('Check Running') {
5
steps {
6
sh 'echo "I am running"'
7
}
8
}
9
stage('Get Random') {
10
steps {
11
sh 'echo $((1 + RANDOM % 10))'
12
}
13
}
14
stage('Complete') {
15
steps {
16
sh 'echo "Pipeline Done"'
17
}
18
}
19
}
20
}

Checkout

To checkout code from a GitHub repo using the GitHub plugin, the following should work under most circumstances:

1
stage('clone') {
2
git branch: env.BRANCH_NAME,
3
url: '<GIT URL>.git'
4
credentialsId: 'credentials_id'
5
}

However for more complex repos which result in timeouts or other issues, it may be a better choice to use the GitSCM method instead, something more like this:

1
stage('clone')
2
checkout([
3
$class: 'GitSCM',
4
branches: [[name: env.BRANCH_NAME]],
5
extensions: [[$class: 'CloneOption', timeout: 30]],
6
gitTool: 'Default',
7
useRemoteConfigs: [[credentialsId: 'credentials_id', url: '<GIT URL>.git']]
8
])

Powershell Plugin Issues

The Powershell plugin often does not exit correctly when using it inside of a Jenkinsfile, a step may have a function like so:

1
powershell """
2
cd ./idontexist
3
"""

Which would throw an error. Jenkins sometimes ignores errors in Powershell scripts, to exit with this correctly, the most reliable way I’ve found is to check if there a non-null $error in the powershell script, and exit with 1 if there is:

1
powershell """
2
cd ./idontexist
3
if($error) { exit 1 }
4
"""