Jenkins LTS Installation, Java 21/25 Runtime Planning, Packages, Containers, and Initial Setup: Diagnostics, Failure Modes, Security, and Performance
Diagnose Jenkins installation failures across Java compatibility, JENKINS_HOME persistence/ownership, ports, bootstrap exposure, plugin/core upgrades, and performance evidence.
Learning objectives
- Diagnose startup and bootstrap failures by preserving the first logs and separating Java, filesystem, network, plugin, and controller-data layers.
- Detect an unsupported Java runtime before Jenkins launch rather than learning through a destructive failed upgrade.
- Recognize ephemeral-home, ownership, port-conflict, and public-bootstrap failures from concrete evidence.
- Explain why core upgrades require Java/plugin/data compatibility review and tested rollback evidence.
- Use the least destructive correction and rerun only the affected scope.
1. Evidence first: preserve the failure before “fixing” it
Installation incidents often become harder because the first response is to restart, delete the container, reinstall Jenkins, or change permissions recursively. Those actions destroy the evidence that would identify the causal layer.
flowchart TD A[Preserve first startup logs + exact command] --> B[Confirm Jenkins core/image/package identity] B --> C[Confirm supported Java runtime] C --> D[Confirm JENKINS_HOME path, mount, ownership, capacity] D --> E[Confirm process/service account and port binding] E --> F[Confirm setup/auth state + plugin baseline] F --> G[Confirm HTTP/proxy reachability] G --> H[Apply smallest correction] H --> I[Restart only required scope and verify persistence]
2. Failure mode: unsupported Java
Current Jenkins LTS requires Java 21 or 25. Instead of launching Jenkins with Java 17 and collecting a predictable failure, make compatibility a preflight gate:
# Safe simulation: inspect an incompatible runtime without launching Jenkins.
docker run --rm eclipse-temurin:17-jre java -version
# Correct controller runtime baseline:
docker run --rm jenkins/jenkins:2.568.3-jdk21 java -version
Diagnosis: if the candidate runtime reports Java 17, the failure belongs to the runtime-compatibility layer. Correct Java before starting the controller. Do not compensate by choosing an obsolete Jenkins core.
3. Failure mode: controller appears new after container replacement
Symptom: yesterday’s controller was configured, but today the replacement container shows “Unlock Jenkins.” Before doing setup again, inspect mounts:
docker inspect jenkins-ch02-controller \
--format '{{json .Mounts}}'
docker volume ls --filter name=jenkins-ch02-home
docker volume inspect jenkins-ch02-home
If the intended volume is not mounted at
/var/jenkins_home, the core process may be healthy
while state attachment is wrong. Stop the new disposable container,
verify the intended volume identity, and recreate the container with
the correct mount. Do not initialize fresh state over an unknown
existing home.
4. Failure mode: permission denied in JENKINS_HOME
A bind mount can exist and still be unusable if its host ownership/mode does not allow the Jenkins process to write. Capture the error first, then inspect both sides:
docker logs --tail 200 jenkins-ch02-controller
docker inspect jenkins-ch02-controller --format 'User={{.Config.User}} Mounts={{json .Mounts}}'
# Inside a running lab container, inspect numeric identity and home permissions.
docker exec jenkins-ch02-controller sh -lc 'id; ls -ldn /var/jenkins_home'
chmod -R 777. It hides the
ownership model by granting broad access. Correct the known
disposable bind mount to the intended service UID/GID and minimum
required permissions instead.
5. Failure mode: port 8080 is already in use
If Docker reports a bind error, Jenkins may never have started. That is a host-listener collision, not a Jenkins application failure.
# Windows PowerShell
Get-NetTCPConnection -LocalPort 8080 -ErrorAction SilentlyContinue |
Select-Object LocalAddress,LocalPort,State,OwningProcess
# Linux
ss -ltnp | grep ':8080 ' || true
Choose an unused loopback host port such as
127.0.0.1:8081:8080 for the disposable lab, or stop the
known conflicting lab service. Do not kill an arbitrary process by
PID without identifying it.
6. Failure mode: setup wizard is reachable from another machine
This is a security defect even if the page “works.” Inspect the port
binding. A Docker binding such as
0.0.0.0:8080->8080 allows network peers to reach the
bootstrap surface subject to firewall/routing.
docker port jenkins-ch02-controller 8080
docker inspect jenkins-ch02-controller \
--format '{{json .HostConfig.PortBindings}}'
For the lab, recreate the controller with
127.0.0.1:8080:8080. For production, design a
controlled TLS/proxy/firewall path. Do not rely on the initial admin
password as the only network control.
7. Failure mode: core upgraded without Java/plugin compatibility review
A core upgrade can fail before startup, during plugin loading, or later in Pipeline behavior. Preserve the old version, plugin inventory, startup logs, and a validated pre-upgrade backup. Read every skipped LTS upgrade guide, not just the destination release notes.
Old core → target core; every skipped LTS line.
Old Java → supported target Java; controller and agents may need coordinated changes.
Installed plugin versions, dependencies, warnings, security advisories, minimum core requirements.
Timestamped pre-upgrade controller-state backup/snapshot tested in isolation.
Controller log from the first failed startup before repeated retries mutate evidence.
Document whether downgrade is supported or requires restoring the pre-upgrade copy.
8. Intentionally broken example: wrong state model
A teammate runs:
docker run --name jenkins-broken -d -p 8080:8080 jenkins/jenkins:2.568.3-jdk21
They configure Jenkins, then run
docker rm -f jenkins-broken and recreate the same
command. The setup wizard returns.
Wrong diagnosis: “Jenkins 2.568.3 does not persist settings.”
Evidence-based diagnosis: no mount targets
/var/jenkins_home; controller state lived only inside
the removed container. The repair is to create an explicit known
volume and repeat the disposable setup. It is not a plugin
reinstall, Java change, or permission bypass.
9. Installation performance: measure before tuning
Slow startup can come from CPU/heap pressure, disk latency in
JENKINS_HOME, plugin initialization,
update-center/network access, DNS/proxy delays, or filesystem
problems. “Give Jenkins more heap” is not a universal fix. Record
startup timestamps and logs, host/container resource limits, disk
free space, and plugin baseline first.
docker stats --no-stream jenkins-ch02-controller
docker exec jenkins-ch02-controller sh -lc 'df -h /var/jenkins_home'
docker logs --timestamps jenkins-ch02-controller | tail -120
10. Minimal correction playbook
| Symptom | First evidence | Likely layer | Least-destructive action |
|---|---|---|---|
| Controller will not start | First startup log + java -version |
Java/core compatibility | Install/select supported Java; do not downgrade core blindly. |
| Fresh setup after replacement | Mount list + volume inventory | Persistence attachment | Reattach verified home volume. |
| Permission denied | Process UID/GID + mount ownership | Filesystem ownership | Correct exact lab mount ownership; avoid world-writable shortcuts. |
| Bind failed | Host listener owner | Network/port | Select another known port or stop identified lab listener. |
| Wizard reachable remotely | Host bind address/firewall | Exposure | Bind loopback in lab; productionize behind controlled proxy/TLS. |
| Upgrade plugin failures | Old/new core + plugin inventory + first log | Core/plugin compatibility | Restore/test pre-upgrade copy; resolve supported plugin path. |
11. Summary
- Preserve first-failure evidence before restart, reinstall, permission changes, or deletion.
- Unsupported Java is a runtime compatibility problem; missing state after replacement is a persistence problem.
- Ownership and port conflicts should be diagnosed with identity evidence, not broad chmod/kill shortcuts.
- Public setup-wizard exposure is a network/bootstrap security failure even when the controller itself is healthy.
- Core upgrades require Java/plugin/data compatibility and a tested state rollback plan—not just an old binary or image.
Knowledge check
A new container shows the setup wizard. Which command should you run before configuring Jenkins again?
Inspect the container mounts and the known home volume.
Reappearing setup often means the intended
JENKINS_HOME was not attached.
Why is chmod -R 777 a poor fix for Jenkins home
permission errors?
It grants broad access, obscures the intended service identity, and may expose secrets. Correct ownership/permissions on the exact lab path instead.
Docker says port 8080 is already allocated. Is that proof Jenkins failed internally?
No. The host port could not be bound, so diagnose the existing listener before reasoning about Jenkins application startup.
What evidence should be preserved before a core/plugin upgrade retry?
Old/new core, Java version, plugin inventory, first startup logs, and a validated pre-upgrade state copy/rollback plan.
Why use an incompatible Java image only as a preflight demonstration rather than launching Jenkins with it?
The learning objective is to detect incompatibility safely before controller startup; deliberately causing a known startup failure adds little and can confuse state/recovery evidence.
Official references and version notes
- Installing Jenkins — official entry point for supported installation methods and new-installation scope.
-
Docker installation
— official Jenkins container image, persistent
/var/jenkins_home, ports, and setup-wizard workflow. - Linux installation — current Debian/Ubuntu, Fedora, and RHEL-family package instructions and service management.
- Windows installation — MSI/service-account guidance, Java selection, port configuration, and setup.
-
WAR-file installation
— standalone Java launch, port selection, and
JENKINS_HOMEoverride. - Java Support Policy — authoritative controller/agent/CLI Java runtime matrix.
- Jenkins LTS changelog — exact LTS release dates, fixes, and tested JDKs.
- Jenkins LTS Upgrade Guide — mandatory reading before upgrades or skipped LTS lines.
- Jenkins Security Advisories — current core/plugin security fixes and affected versions.
Version-sensitive statements in this lesson were rechecked on
2026-09-14. The lab baseline is
Jenkins 2.568.3 LTS on Java 21;
Jenkins 2.568.3 is also tested with Java 25. Current Jenkins LTS
releases in this line require Java 21 or 25. The disposable
container examples pin the human-readable image tag
jenkins/jenkins:2.568.3-jdk21 and require learners to
record the locally resolved RepoDigest after pulling
it. Re-check the LTS changelog, Java policy, image tags/digests,
package signing key, and security advisories when regenerating
this lesson.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.