Book Image

Jenkins Administrator's Guide

By : Calvin Sangbin Park, Lalit Adithya, Sam Gleske
Book Image

Jenkins Administrator's Guide

By: Calvin Sangbin Park, Lalit Adithya, Sam Gleske

Overview of this book

Jenkins is a renowned name among build and release CI/CD DevOps engineers because of its usefulness in automating builds, releases, and even operations. Despite its capabilities and popularity, it's not easy to scale Jenkins in a production environment. Jenkins Administrator's Guide will not only teach you how to set up a production-grade Jenkins instance from scratch, but also cover management and scaling strategies. This book will guide you through the steps for setting up a Jenkins instance on AWS and inside a corporate firewall, while discussing design choices and configuration options, such as TLS termination points and security policies. You’ll create CI/CD pipelines that are triggered through GitHub pull request events, and also understand the various Jenkinsfile syntax types to help you develop a build and release process unique to your requirements. For readers who are new to Amazon Web Services, the book has a dedicated chapter on AWS with screenshots. You’ll also get to grips with Jenkins Configuration as Code, disaster recovery, upgrading plans, removing bottlenecks, and more to help you manage and scale your Jenkins instance. By the end of this book, you’ll not only have a production-grade Jenkins instance with CI/CD pipelines in place, but also knowledge of best practices by industry experts.
Table of Contents (13 chapters)
12
Index

Running a Jenkins controller with Docker on HTTPS

Let's dive right into deploying a Jenkins controller with Docker on HTTPS.

Custom image to match the UID/GID for a bind mount

We may need to customize the UID/GID of the user inside the container.

Let's take a look at the Dockerfile for the jenkins/jenkins image, lines 20 to 26 (https://github.com/jenkinsci/docker/blob/jenkins-docker-packaging-2.235.1/Dockerfile):

Figure 2.1 – UID mismatch warning in a Jenkins Dockerfile

Our Jenkins controller Docker container does bind mount a volume from the host, and therefore the directory on the host must be owned by a UID and GID that matches the user inside the container. The default user inside the container is jenkins, which has UID 1000 and GID 1000.

On an AWS EC2 Ubuntu 20.04 instance, the default ubuntu user is already 1000:1000, so no changes are necessary:

ubuntu@aws-controller:~$ echo "$(whoami) $(id -u) $(id -g)"
ubuntu 1000 1000

On a VM in the corporate network, the user for running Jenkins may not be 1000:1000. This is especially true if you are using a robot account with its UID/GID predefined in the corporate Active Directory. In our example, robot_acct has UID 123 and GID 30, which we cannot change:

robot_acct@firewalled-controller:~$ echo "$(whoami) $(id -u) $(id -g)"
robot_acct 123 30

In such a case, we need to extend the Docker image to change the UID/GID of the jenkins user to match our robot account, so that the files created from inside the container by the jenkins user are accessible on the host by the robot_acct user, as illustrated in Figure 2.2:

Figure 2.2 – Container user and host user with matching UID/GID

  1. Create the following Dockerfile. Let's use the 2.263.1-lts tag for now – we will upgrade to the latest LTS in Chapter 8, Upgrading the Jenkins Controller, Agents, and Plugins:

    jenkins.dockerfile

    FROM jenkins/jenkins:2.263.1-lts
    USER root
    RUN  usermod -u 123 -g 30 jenkins
    USER jenkins
  2. Build the image and name it <Docker Hub ID>/jenkins:2.263.1-lts:
robot_acct@firewalled-controller:~$ docker build 
-t calvinpark/jenkins:2.263.1-lts -f jenkins.dockerfile .
[...]
Successfully tagged calvinpark/jenkins:2.263.1-lts

All users now have a matching UID/GID and we avoid a headache with file permission issues.

Running Jenkins

Let's launch the Jenkins controller. This is what the architecture looks like:

Figure 2.3 – Architecture of VMs and containers for Jenkins controllers

Let's begin:

  1. Create jenkins_home. Skipping this will cause Docker to create the directory as root, causing Jenkins to fail with permission issues:
    controller:~$ mkdir jenkins_home
  2. Then, run the Jenkins container. We can use jenkins/jenkins on an AWS controller or our custom image on a firewalled controller:
    controller:~$ docker run \
    --detach \
    --restart on-failure \
    -u $(id -u):$(id -g) \
    -v ~/jenkins_home:/var/jenkins_home \
    -p 8080:8080 -p 50000:50000 \
    --name jenkins_controller \
    calvinpark/jenkins:2.263.1-lts

    There are a few flags in this command. Let's examine what they mean:

    • --detach: Run in the background.
    • --restart on-failure: Automatically restart if the container crashes or the machine reboots.
    • -u $(id -u):$(id -g): Run as the UID and GID of the host user.
    • -v ~/jenkins_home:/var/jenkins_home: Bind mount the host ~/jenkins_home directory to /var/jenkins_home inside the container so that the Jenkins data is written on the host directory.
    • -p 8080:8080: Bind TCP port 8080 on the host to port 8080 inside the container. Jenkins, by default, runs HTTP on 8080. Traffic to HTTP port 80 and HTTPS port 443 will be forwarded to port 8080 through a reverse proxy.
    • -p 50000:50000: This port is for inbound agents. If your Jenkins will not have any inbound agents, this port doesn't need to be bound.
    • --name jenkins_controller: Name the running container jenkins_controller for a memorable name and easier access.
  3. Verify that the container is running and didn't crash:
    controller:~$ docker ps
    CONTAINER ID   IMAGE                         COMMAND
    CREATED STATUS PORTS
    NAMES
    597e509542eb   jenkins/jenkins:2.263.1-lts   "/sbin/tini -- /
    usr/…" 5 seconds ago Up 4 seconds 0.0.0.0:8080->8080/tcp,
    0.0.0.0:50000->50000/tcp jenkins_controller
  4. In a minute, Jenkins should be up and running. Open a web browser to the IP of your VM on port 8080 to see a prompt to unlock Jenkins. If you're on AWS, the IP should be the public IP of your VM, such as http://54.70.250.76:8080. If you're using a VM inside the corporate firewall, the IP should be the IP of your VM, such as http://192.168.1.16:8080:

    Figure 2.4 – First boot unlock prompt

  5. We can find the initial admin password in the ~/jenkins_home/secrets/initialAdminPassword file:
    controller:~$ cat ~/jenkins_home/secrets/initialAdminPassword
    98b13e64bebf4003844baa863d1dc2fd
  6. Copy and paste the value into the password box in the browser and click Continue.
  7. At the Customize Jenkins screen, click Install suggested plugins to continue. We will install more packages soon.

    In a few minutes, Jenkins finishes installing the plugins and asks you to create the admin user. Do not skip this step! The default password for admin is the long string that you had to look up before, and now is the best time to change it:

    Figure 2.5 – First boot Create First Admin User screen

  8. Finally, it asks us to configure the Jenkins URL. Click Save and Finish to continue (we will change this soon), and then click Start using Jenkins:

Figure 2.6 – Jenkins is ready

Jenkins is fully up and running. While we can start using Jenkins as is, let's continue to set up a reverse proxy and HTTPS so that the URL is easier to remember and the traffic is encrypted.

Locked out?

If you didn't change the admin password during the first boot, you'll need an admin password to get back into Jenkins. The password is the long string in ~/jenkins_home/secrets/jenkins_controller.