Implementing Jenkins as Code with Docker and Configuration‑as‑Code
This article describes how to create an immutable Jenkins instance by storing all configuration and job definitions as declarative code, building a Docker image with required plugins, using the Configuration‑as‑Code and Job‑DSL plugins, and automating setup tasks such as default user creation and wizard skipping across multiple environments.
Since I started working with Jenkins, I have been using it for everything from supervising legacy jobs to maintaining and enhancing declarative multi‑branch pipelines, aiming to achieve continuous integration and delivery across many environments.
Achieving this level of automation requires time, team effort, and a cultural shift toward DevOps practices.
The goal is to build a Jenkins instance whose entire configuration and job definitions are stored in declarative files, making the instance immutable, version‑controlled in Git, and reproducible on any host for testing or production.
To accomplish this, I split the project into two repositories: one for instance‑level configuration (using the Configuration‑as‑Code plugin and a Dockerfile to build a base image) and another for job definitions via the Jenkins DSL plugin, storing jobs, folders, and views as Groovy code.
Building the Docker image
FROM jenkins/jenkins:lts
COPY init-scripts /usr/share/jenkins/ref/init.groovy.d
ADD plugins.txt /usr/share/jenkins/ref/
ADD jenkins.yaml /usr/share/jenkins/ref/
RUN /usr/local/bin/install-plugins.sh < /usr/share/jenkins/ref/plugins.txt
ENV CASC_JENKINS_CONFIG /usr/share/jenkins/ref/
VOLUME /var/jenkins_homeA helper shell script can build and run the image:
#!/usr/bin/env bash
docker build -t jenkins_as_code:0.1.0 .Plugin installation
The install-plugins.sh script bundled in the Jenkins image installs plugins listed in plugins.txt , allowing version locking.
workflow-aggregator:2.6
configuration-as-code:1.30
configuration-as-code-support:1.18
credentials:2.3.0
blueocean:1.19.0
job-dsl:1.74JCaC Jenkins plugin
This plugin lets you define global and plugin configuration via a YAML file, enabling immutable deployments and even a seed job that pulls DSL scripts from a Git repository.
jenkins:
systemMessage: "Jenkins As Code Concept."
views:
- myView:
name: "Jobs Config as Code"
security:
globalJobDslSecurityConfiguration:
useScriptSecurity: false
jobs:
- script: >
freeStyleJob("Jobs Generator") {
scm {
github('imanol-dev/jenkins_as_code_jobs', 'master')
}
steps {
dsl {
external('*.groovy')
}
}
}Changing the YAML and reloading applies all updates without recreating the Jenkins container.
Default admin user
To auto‑create a default admin, set the following environment variables in the container:
ADMIN_USERNAME=
ADMIN_PASSWORD=Skipping the setup wizard
Disable the initial setup wizard by providing:
JAVA_OPTS="-Djenkins.install.runSetupWizard=false"Job DSL plugin and job definitions
Jobs can be defined in a separate repository and triggered via a seed job; any changes to the DSL scripts are automatically applied, eliminating manual updates.
Conclusion
While a single Jenkins instance can serve multiple environments, sometimes isolated instances are required; using Jenkins as Code with Docker, Configuration‑as‑Code, and Job‑DSL provides a repeatable, version‑controlled way to automate repetitive and manual tasks across those instances.
DevOps Cloud Academy
Exploring industry DevOps practices and technical expertise.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.