CI/CD as Code Part II – Installing and Setting up Jenkins Programmatically

Stateless Jenkins Container with Docker: Installing and setting up Jenkins Programmatically

The purpose of this sample series is to create a simple set of examples, which showcases CI/CD as Code, using Jenkins. The primary goal is to create a stateless CI/CD setup, which can be bootstrapped from a set of configuration files and scripts so that many problems related to maintenance of the infrastructure and other operational issues are reduced.

We created a containerized Jenkins instance in the previous part of these example series. Moreover, we did most of the installation and configuration work via the user interfaces. In contrast to this, our target in this step is to automate most of the manual work so that we are one step closer to a stateless Jenkins Docker container. 

Checkout the example code from here

In summary, this basic setup will handle the following on behalf of an actual human being:

  1. Creation of the user(s) on Jenkins programmatically.
  2. Installation of basic plugins to get up and running with Jenkins.

Creating the initial admin user for Jenkins programmatically

Jenkins provides a set of scripted execution mechanisms to allow automation in delivery processes using certain key Jenkins events. This mechanism is called “hook scripts“. In this step, we are going to introduce “Post-initialization scripts” from this set to our container.

The “post-initialization” scripts are located at

/usr/share/jenkins/ref/init.groovy.d/ in a standard Jenkins setup. Accordingly, to use this feature in our container, we will add a folder named
init.groovy to our codebase and map the contents of this folder to our container’s post-initialization scripts directory:

Add the following command to your Dockerfile
ADD init.groovy/ /usr/share/jenkins/ref/init.groovy.d/

The next step is to implement the script, which will create the initial admin user for us. Create a groovy script file under init.groovy named “0-disable-login.groovy” directory and paste the following code:

Note that, post-initialization scripts are executed in alphabetical order by Jenkins. This is why the prefix “0” is used for user creation script.

Adding an initial set of necessary Jenkins plugins programmatically

In this step, we need to collect a list of necessary Jenkins plugins for our setup. You can use recommended plugins in a standard Jenkins installation for the sake of simplicity. Getting the list is relatively easy, but we need to use Jenkins Interface again.  Let’s run our container, which we created in the previous step, then complete the setup via the user interface. As soon as you finish the setup, you can either use the Jenkins scripting interface located at “http://yourhost:port/script” or use the API provided by Jenkins.

Getting the list using a script:

Getting the list using the API:

curl --user admin_groovy:123456 "http://localhost:7080/pluginManager/api/json?depth=1"

Now that you have the plugin list at hand, create a file named plugins under configs directory and paste the short names of the plugins to this file.

Excerpt of the plugins file:

ace-editor
ant
antisamy-markup-formatter
apache-httpcomponents-client-4-api
authentication-tokens
bouncycastle-api
branch-api build-timeout
cloudbees-folder
... 

The next step is to add the necessary configuration to our Dockerfile to automate Jenkins plugin installation. Jenkins Docker Image already has a script to handle this job from the command line.  Add the following configuration to your Dockerfile. 

COPY configs/plugins /var/jenkins_init_config/plugins
RUN /usr/local/bin/install-plugins.sh < /var/jenkins_init_config/plugins

The container can be tested after completing this step. Build your container, run it and check if everything works as expected from the user interface.