Jenkins Docker Image with JCasC

So I’m at Jenkins/Devops World this week and had some free time to mess with a tool I’ve been meaning to look into for some time: JCasC.

This tool allows you to manage the Jenkins config via 1 or many yaml files.

I’m used to using Jenkins master in a docker container and wanted to setup a docker image that has Jenkins setup with a default JCasC yaml so you can get started with Jenkins all setup to manage via code. So here it is:

Dockerfile

Here is the Dockerfile, it’s pretty basic, it pulls down an lts jenkins img. It copies the plugins.txt file and runs a install-plugins.sh script that is provided by the Jenkins org (or maybe Cloudbees?). It copies the JCasC yaml over and the last part is to disable the setup wizard to run. We don’t need the setup wizard to run because we are going to setup everything via our jenkins.yaml

$ cat Dockerfile
FROM jenkins/jenkins:lts

# Install plugins
COPY plugins.txt /usr/share/jenkins/ref/plugins.txt
RUN /usr/local/bin/install-plugins.sh < /usr/share/jenkins/ref/plugins.txt

# Copy Jenkins config as code
COPY jenkins.yaml /var/jenkins_home/jenkins.yaml

# Set java options.
ENV JAVA_OPTS -Djenkins.install.runSetupWizard=false

Here is the jenkins.yaml file. Again, pretty basic, the important parts are the users list, this will setup an admin user so you can login to the interface.

The rest of the config are security enhancements like enabling CSRF, disabling remoteCLI, etc.

$ cat jenkins.yaml
jenkins:
  securityRealm:
    local:
      allowsSignup: false
      users:
        - id: "admin"
          password: "${admin_pass}"

  authorizationStrategy:
    loggedInUsersCanDoAnything:
      allowAnonymousRead: false

  # Enable CSRF
  crumbIssuer:
    standard:
      excludeClientIPFromCrumb: false

  # Enable Slave to Master Access Control
  remotingSecurity:
    enabled: True

security:
  remotingCLI:
    enabled: false

Here is the plugins.txt file, you can add multiple lines of plugins with their versions here.

$ cat plugins.txt
configuration-as-code:1.27

Now when you build the image and run it you have to pass in the admin password like so: docker run -e admin_pass=test1 -p 8080:8080 -p 50000:50000 jenkins

Gotchas

The main gotcha is that there isn’t persistent storage.
The Official Jenkins Docker image page says that you can use a named volume by adding -v jenkins_home:/var/jenkins_home to your docker run command. However if you do that and then make any manual changes to the jenkins config or install/update/remove plugins then those changes will persist on the volume, and therefore will basically make the JCasC and plugins-install script not reflect what is live.

1 method to get around this is you could have a job that applies the JCasC jenkins.yaml file often, then if anyone tries to make manual changes, the job will set it back to what’s in the jenkins.yaml.

Next steps.

  • Figure out how to setup persistent storage, perhaps just for the jobs directory?
  • Add in more settings (like cloud) to the jenkins.yaml.
  • Split up the jenkins.yaml into multiple yaml files so it’s easier to read.

Part 2

I added more to this docker image, you can read more about it here