Jenkins Tutorial: Get Started Quickly and Easily With CI

9 min read

Introduction

What’s the first thing you think of when someone refers to continuous integration (CI)? For many people, it’s Jenkins®. Originally developed just for CI, Jenkins manages and controls software delivery processes throughout the entire lifecycle. It’s now the most widely used software process automation, continuous integration and continuous delivery tool in the world.

This tutorial focuses on CI. You’ll learn how to build a Jenkins server and create a CI job. Then you’ll finish up by starting an automatic build as the result of a code change.

What Is CI?

CI means integrating code quickly. Rather than operating on a schedule or waiting for the project to cross predefined gates, developers frequently push their changes to a shared repo. Then, Jenkins or another similar tool detects the changes and starts a build.

There are many reasons to implement CI. When you integrate and build your code early and often, it helps you detect problems and conflicts early on, rather than weeks or even months after they’re created. You also help your developers by getting the feedback earlier too.

What Is Jenkins?

Jenkins is an open-source automation server. You can use it to automate nearly any task. Most importantly, you can also trigger these tasks based on events like changes to a source code repository. That’s what makes it a powerful tool in the software development process.

Let’s get Jenkins up and running quickly!

Prerequisites

The fastest way to get started with Jenkins is with the latest Docker image. It contains everything you need to get a server up and running. So you’ll need a system with Docker installed

You’re also going to use Docker Compose to add a Jenkins agent to the server, so you’ll be able to set up a simple project.

Finally, you’ll need access to a Git repo. For this example, I’ll use one on GitHub, which you can fork and use for this tutorial.

Installing and Configuring Jenkins

Start a Jenkins Server

First, you need to start a Jenkins server and unlock it.

Create an empty directory. Then create a file named docker-compose.yaml with your favorite text editor.

Here is the initial configuration.

# docker-compose.yaml

version: '3.7'

services:

  jenkins:

    image: jenkins/jenkins:lts

    privileged: true

    user: root

    ports:

      - 8080:8080

      - 50000:50000

    container_name: jenkins

    volumes:

      - /jenkins_compose/jenkins_configuration:/var/jenkins_home

The service, which starts on line three, is the Jenkins server. It has several important properties.


image: You’re using the latest long-term support Jenkins image.
user: Jenkins will run as root in the container.
ports: The server will listen on port 8080 for web connections. The other port is for build agents.
container_name: Rather than using a randomly generated container name each time you run the service, set it to jenkins.
volumes: This volume stores configuration data so it survives restarting the container. Use a local path on your system.

Start this container with docker-compose up -d in the directory where you placed the configuration.

egoebelbecker@zaku:~/jenkins_compose$ docker-compose up -d


Creating jenkins ... done

You can verify that your container is running with docker ps.

egoebelbecker@zaku:~/jenkins_compose$ docker ps -a

CONTAINER ID        IMAGE                     COMMAND

CREATED             STATUS              PORTS

NAMES

fcfe73288011 jenkins/jenkins:lts "/sbin/tini -- /usr/…"

About an hour ago Up About an hour 0.0.0.0:8080->8080/tcp,

0.0.0.0:50000->50000/tcp jenkins

You’ll see a container named jenkins.

Next, point a web browser at your server. If you can run on a browser on the same host, point your web browser at 127.0.0.1:8080. If not, use the IP address of your Docker server.

You need the password from the log to unlock that server. So go back to the prompt and run docker logs jenkins. Look for three lines of asterisks and a message like this:

2021-06-12 23:53:23.868+0000 [id=34] INFO

jenkins.install.SetupWizard#init:

*************************************************************

*************************************************************

*************************************************************

Jenkins initial setup is required. An admin user has been created and a password generated.

Please use the following password to proceed to installation:

2df2903029634350a69d0b05a5af17fe

This may also be found at: /var/jenkins_home/secrets/initialAdminPassword

*************************************************************

*************************************************************

*************************************************************


Copy the password, paste it into the prompt, and click the “Continue” button on the bottom of the page. This takes you to the plugins page.

Click “Install suggested plugins,” and wait for them to finish installing. Next, the installation prompts you for an admin user.

So enter information for the administrator login.

You now have a Jenkins server!

Create a User

Click through the next couple of pages, and you’ll end up on the main dashboard.

Now, create an unprivileged user since you don’t want to run builds as the administrator.

Click on “Manage Jenkins.” Then on “Manage Users.” This takes you to the user page.

Next, click on “Create User.”

Fill in your new user’s information and click “Create User.”

You’ve added an unprivileged user. Now, it’s finally time to create a new CI job.

Add a CI Job

Git Repository

To set up a CI job, you need a Git repo for Jenkins to pull code from. For this tutorial, I’ll use a URL for a publicly accessible repository. Fork this repo so you can make changes for the automated build test.

Once you’ve forked the repo, get the URL.

Add the Job

Before you add your first build job, log out of Jenkins and log back in as your new user.

Then, click “Create a job” in the center of the dashboard.

This takes you to the item entry page.

Give your job a name. Select “Freestyle project.” Then click “OK.”

Now you’re on the job detail page. Start at the “Source Code Management” tab.

Enable Git under “Source Code Management.” Then add your repo URL and set the “Branch Specifier” to /main since that’s the default branch for a new GitHub repository.

Next, go to the “Build” tab and find the “Build” section of the job details page.

Click the “Add Build Step” button. This will open a menu where you can select from several options. Select “Execute shell.”

Enter cat README.md into the test area. This is the shell command Jenkins will execute for each CI job.

Click “Save.”

You’ve created a build job.

Run a Build Job

So let’s run the build and see what happens.

When you saved the job, Jenkins took you to the job status page. You can manually kick off a build by clicking on “Build Now.”

This build only takes a few seconds to run. When it finishes, you’ll see the build number in the “Build History” area.

Click on the build number and select “Console Output.”

The console output is plain text, but a few key lines are in bold here. They won’t be on your server.

Started by user Build User

Running as SYSTEM

Building in workspace /var/jenkins_home/workspace/test_job

The recommended git tool is: NONE

No credentials specified

Cloning the remote Git repository

Cloning repository https://github.com/egoebelbecker/simple_repo.git

 > git init /var/jenkins_home/workspace/test_job # timeout=10

Fetching upstream changes from https://github.com/egoebelbecker/simple_repo.git

 > git --version # timeout=10

 > git --version # 'git version 2.11.0'

 > git fetch --tags --progress -- https://github.com/egoebelbecker/simple_repo.git +refs/heads/*:refs/remotes/origin/* # timeout=10

 > git config remote.origin.url https://github.com/egoebelbecker/simple_repo.git # timeout=10

 > git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* # timeout=10

Avoid second fetch

 > git rev-parse refs/remotes/origin/main^{commit} # timeout=10

Checking out Revision 45b6ec68d90e3235b3474c3d827394e0715a7df2 (refs/remotes/origin/main)

 > git config core.sparsecheckout # timeout=10

 > git checkout -f 45b6ec68d90e3235b3474c3d827394e0715a7df2 # timeout=10

Commit message: "Update README.md"

First time build. Skipping changelog.

[test_job] $ /bin/sh -xe /tmp/jenkins1484436943644585798.sh

+ cat README.md

# simple_repo

This is a dummy repo with only a README.md file.

Finished: SUCCESS

You can see that Jenkins checked out the repository and then ran the build. Since our build simply prints out the readme file, it passes.

Trigger a Build Job

This takes care of the first part of CI—automatically building code. Now to add the most important step: building when the repository changes.

Click “Configure” and go to the “Build Triggers” tab.

Select “Poll SCM.” This will poll GitHub periodically for changes. Enter the schedule above. This entry tells Jenkins to check for changes every five minutes.

Now, edit the README.md and commit and push the change.

After a few minutes, Jenkins will start another build. When it finishes, take a look at the build log.

Started by an SCM change

Running as SYSTEM

Building in workspace /var/jenkins_home/workspace/test_job

The recommended git tool is: NONE

No credentials specified

 > git rev-parse --resolve-git-dir /var/jenkins_home/workspace/test_job/.git # timeout=10

Fetching changes from the remote Git repository

 > git config remote.origin.url https://github.com/egoebelbecker/simple_repo.git # timeout=10

Fetching upstream changes from https://github.com/egoebelbecker/simple_repo.git

 > git --version # timeout=10

 > git --version # 'git version 2.11.0'

 > git fetch --tags --progress -- https://github.com/egoebelbecker/simple_repo.git +refs/heads/*:refs/remotes/origin/* # timeout=10

 > git rev-parse refs/remotes/origin/main^{commit} # timeout=10

Checking out Revision 6ff95003904841c2a8664598a3a052a3efce13ea (refs/remotes/origin/main)

 > git config core.sparsecheckout # timeout=10

 > git checkout -f 6ff95003904841c2a8664598a3a052a3efce13ea # timeout=10

Commit message: "Updating readme to trigger a build."

 > git rev-list --no-walk 45b6ec68d90e3235b3474c3d827394e0715a7df2 # timeout=10

[test_job] $ /bin/sh -xe /tmp/jenkins809505298264427884.sh

+ cat README.md

# simple_repo

This is a dummy repo with only a README.md file.


This change should trigger a build.

Finished: SUCCESS

The build console shows the latest commit message and the successful build results.

Conclusion

In this tutorial, you set up a new Jenkins server using Docker and Docker Compose. After completing the basic server configuration, you set up a new build job. You ran the job manually and then configured a CI job by telling Jenkins to start a new build every time the repository changes.

With its ease of use and nearly unlimited power, it’s easy to see why Jenkins is so often used for CI. If you’re not already using it to control your CI pipelines, take a look and see how you can speed your integrations and make life easier for your developers.

If your team uses Jenkins and you'd like to learn more about managing and scaling it for the enterprise, check out this eBook.

This post was written by Eric Goebelbecker. Eric has worked in the financial markets in New York City for 25 years, developing infrastructure for market data and financial information exchange (FIX) protocol networks. He loves to talk about what makes teams effective (or not so effective!).

Stay up to date

We'll never share your email address and you can opt out at any time, we promise.