Chapter 08Lesson 01~100 minutes

Tool Installations, JDKs, Maven, Gradle, Node.js, Docker CLI, and Reproducible Build Environments: Concepts, Architecture, and Mental Model

Build a precise toolchain mental model: Jenkins records tool metadata, but the executable that actually runs lives on an agent or inside a container and must be identified, versioned, and tied to the artifact it produced.

ToolchainsJDK vs Jenkins JVMMaven/GradleNode.jsDockerReproducibility

Learning objectives

  • Distinguish the Java runtime that runs Jenkins from the JDK used to compile or test an application.
  • Explain how Jenkins global tool definitions, agent-local binaries, project wrappers, and container images select executables.
  • Record agent OS/architecture, PATH, JAVA_HOME, exact tool versions, wrapper metadata, and image digests as build evidence.
  • Explain why a mutable image tag, auto-installer result, or PATH entry is not by itself a reproducible toolchain identity.
  • Recognize Docker socket access as a privilege boundary rather than a harmless convenience.

1. The problem: “it built on Jenkins” is not a toolchain specification

Two Jenkins builds can run the same source revision and still produce different bytes because they used different JDKs, Maven or Gradle releases, Node.js runtimes, native libraries, package-manager lockfiles, or container images. Jenkins schedules work; it does not magically make every agent identical.

A useful build record therefore answers: which controller/job requested the build, which agent actually executed it, what operating system and architecture the agent had, which executable path was resolved for each tool, which exact versions ran, how dependencies were pinned, and which artifact digest came out.

Chapter 08 rule: treat the toolchain as versioned input to the build. Record it with the same seriousness as the source commit.

2. Mental model: requirement → resolution → execution → evidence

A job or Pipeline expresses a requirement such as “use JDK 21 and Maven.” Jenkins may satisfy that requirement through a named global tool definition, an executable already present on the agent, a project wrapper, or a container image. Those mechanisms are not equivalent: they place ownership, update cadence, trust, caching, and rollback in different layers.

Toolchain causality — the executable that runs is the evidence-bearing state
flowchart TD
  A[Job/Pipeline tool requirement] --> B{Resolution strategy}
  B --> C[Jenkins named tool / installer]
  B --> D[Agent-preinstalled binary]
  B --> E[Project wrapper + lockfiles]
  B --> F[Container image by tag/digest]
  C --> G[Resolved executable path + version]
  D --> G
  E --> G
  F --> G
  G --> H[Build + dependency resolution]
  H --> I[Artifact + checksum/digest]
  I --> J[Toolchain evidence packet]

The arrow from “strategy” to “resolved executable” is where many incidents hide. A UI label named jdk21 is only metadata until you prove the executable path and java -version or javac -version on the assigned agent.

3. Separate controller metadata from agent reality

Layer Typical state What to verify
Controller Named tool definitions, installer metadata, plugin versions. Tool name, installer source/version, owning plugin, configuration revision.
Agent OS/arch, filesystem, PATH, JAVA_HOME, preinstalled binaries. uname/ver, architecture, resolved executable, exact version.
Project Maven/Gradle wrapper, package manager config, lockfiles. Wrapper scripts/JAR/properties, checksum policy, lockfile revision.
Container Image filesystem and entrypoint. Registry, tag, resolved digest, image labels/SBOM where available.
Build Commands, dependency graph, produced files. Tool version output, dependency lock verification, artifact checksum.

4. Jenkins runtime Java is not the application build JDK

Current Jenkins 2.568.3 LTS is tested with Java 21 and 25. That requirement governs the JVM used to run the controller and agent process. Your application may still need a different supported build JDK, provided the agent process itself has a supported Jenkins runtime. Keep these identities separate in diagrams, logs, and incident notes.

On an agent, inspect both the Java process used by Jenkins and the build JDK selected for a job. If an old application still compiles with JDK 17, for example, the agent can run Jenkins Remoting on Java 21 while the build step invokes a separately installed JDK 17 toolchain. Do not “fix” Jenkins runtime compatibility by downgrading the JVM that runs the agent.

5. Jenkins tool definitions: names are indirection

Manage Jenkins → Tools can define named installations. Declarative Pipeline can request configured jdk, maven, or gradle tools with the tools directive. Jenkins then exposes the selected installation for the relevant agent context. The name must match a configured installation.

pipeline {
  agent { label 'lab-linux' }
  tools {
    jdk 'jdk21-build'
    maven 'maven-3.9'
  }
  stages {
    stage('Prove toolchain') {
      steps {
        sh 'java -version'
        sh 'javac -version'
        sh 'mvn -B -V --version'
      }
    }
  }
}

The configuration name is useful for policy, but evidence must still include the version output from the executable that actually ran.

6. Project wrappers move version intent closer to source

Maven Wrapper and Gradle Wrapper let the repository carry the intended build-tool version and bootstrap logic. This improves portability because a developer laptop and Jenkins agent can invoke ./mvnw or ./gradlew from the same source revision. It does not eliminate trust requirements: wrapper scripts, wrapper JARs, distribution URLs, and checksums are executable supply-chain inputs.

Commit wrapper metadata deliberately, review changes, and use checksum verification where the wrapper ecosystem supports it. A missing or unexpectedly modified wrapper is a build-integrity failure, not a reason to silently fall back to whatever mvn or gradle happens to be on PATH.

7. Node.js adds runtime and dependency-manager identity

For Node.js projects, record the Node runtime plus the package manager and lockfile behavior. A package-lock.json, pnpm-lock.yaml, or Yarn lockfile is part of dependency reproducibility, but it does not pin the Node runtime by itself. Use project metadata, a version manager policy, a Jenkins plugin if deliberately governed, or a pre-baked/container toolchain to select the runtime.

Prefer deterministic install modes such as npm ci when the project uses npm and has a compatible lockfile; do not silently regenerate lockfiles in CI.

8. Docker can freeze a filesystem, but the daemon is a trust boundary

Docker Pipeline can run stages inside a selected image, making compiler/runtime packages more explicit. Tags are human-friendly references and can move; for release-sensitive builds, record the resolved image digest and use digest pinning where your registry workflow permits it.

Do not normalize mounting /var/run/docker.sock into untrusted jobs. Access to a host Docker daemon can usually be turned into host-level control. Put image-building work on isolated, purpose-built agents or use a safer remote/rootless/build-service design appropriate to your environment.

9. Read-only inspection before changing anything

printf 'node=%s\nworkspace=%s\n' "$NODE_NAME" "$WORKSPACE"
uname -a || true
printf 'PATH=%s\n' "$PATH"
printf 'JAVA_HOME=%s\n' "${JAVA_HOME:-unset}"
java -version
javac -version || true
mvn -B -V --version || true
gradle --version || true
node --version || true
npm --version || true
docker version --format '{{.Client.Version}}' 2>/dev/null || true

Do not dump all environment variables because credentials or other sensitive values may be present. Inspect only the toolchain fields needed for evidence.

10. DevOps connection: reproducibility is a provenance chain

A defensible artifact ties source revision to agent identity, toolchain resolution, dependency lock state, command line, and artifact digest. That evidence lets another engineer explain why two builds differ instead of guessing from a green Jenkins badge.

Next lesson

Guided Hands-On Workflow and Core Operations

Compare a Jenkins-managed/native toolchain with a project-owned wrapper or isolated container strategy, then capture exact toolchain and artifact evidence.

Knowledge check

Why is the name jdk21-build not enough evidence?

Can an agent run Jenkins Remoting on Java 21 while compiling an application with another JDK?

What should happen if a committed wrapper is missing or unexpectedly modified?

Why is a Docker image tag weaker evidence than a digest?

Why is Docker socket access security-sensitive?

Official references and version notes

Version and compatibility note

Rechecked on 2026-09-16. Examples assume Jenkins 2.568.3 LTS, tested with Java 21 and 25. The lab uses Java 21 for the Jenkins controller/agent runtime, but deliberately treats the application build JDK as separate state. Declarative tools supports Jenkins-configured jdk, maven, and gradle tools. Docker-based Pipeline examples are optional and require the Docker Pipeline plugin plus a deliberately isolated Docker-capable agent; the mandatory path does not mount a host Docker socket into untrusted builds.

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.