Chapter 02Lesson 04~105 minutes

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.

InstallationJenkins LTSJava 21/25JENKINS_HOMEEvidence-first

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.

Installation diagnostic ladder
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'
Avoid 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.

Core delta

Old core → target core; every skipped LTS line.

Java delta

Old Java → supported target Java; controller and agents may need coordinated changes.

Plugin delta

Installed plugin versions, dependencies, warnings, security advisories, minimum core requirements.

State copy

Timestamped pre-upgrade controller-state backup/snapshot tested in isolation.

First failure

Controller log from the first failed startup before repeated retries mutate evidence.

Rollback limit

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.
Next lesson

Checkpoint Lab — Installation and Runtime Planning

Run a deliberately failed storage/runtime preflight, then build the correct controller, prove persistence and identity, and tear down only the named disposable resources.

Knowledge check

A new container shows the setup wizard. Which command should you run before configuring Jenkins again?

Why is chmod -R 777 a poor fix for Jenkins home permission errors?

Docker says port 8080 is already allocated. Is that proof Jenkins failed internally?

What evidence should be preserved before a core/plugin upgrade retry?

Why use an incompatible Java image only as a preflight demonstration rather than launching Jenkins with it?

Official references and version notes

Version and compatibility note

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.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.