Skip to content

HOWTO – Bootstrap Jenkins Docker Agent on Control Node (ctrl-01)

Provision a Docker-based Jenkins inbound agent on ctrl-01 so pipeline workload executes off the controller. This HOWTO uses JCasC to define the node and the jenkins_agents_docker role to run the tools-enabled inbound agent container on the controller host.

Difficulty: Intermediate
Prerequisites: Jenkins controller deployed (via jenkins_controller), Docker Engine installed, and admin credentials available via your secrets strategy.


Demo

No academy walkthrough recording is linked here yet.

Context

This HOWTO is used during the bootstrap / transition phase:

  • Jenkins controller is already running on ctrl-01.
  • RKE2 pod agents are not yet available (or are temporarily unavailable).
  • You still need a governed agent runtime to execute platform pipelines.

It aligns with:


Steps

1. Ensure the node exists via JCasC (no Script Console)

Define the ctrl-docker node in controller JCasC (recommended for hardened Jenkins). Example snippet:

jenkins:
  nodes:
    - permanent:
        name: "ctrl-docker"
        remoteFS: "/home/jenkins"
        numExecutors: 1
        mode: NORMAL
        labelString: "ctrl-docker"
        retentionStrategy: "always"
        launcher:
          inbound:
            webSocket: false

Expected result:

  • Jenkins starts cleanly (no JCasC boot failures).
  • The node exists in Jenkins once the controller is up.

2. Run the inbound agent container on ctrl-01

Apply your playbook that includes hybridops.app.jenkins_agents_docker.

Example variables (hardened mode):

jenkins_agents_docker_manage_node: false
jenkins_agents_docker_agent_secret: "{{ vault_ctrl_docker_agent_secret }}"
jenkins_agents_docker_use_websocket: false

Run:

ansible-playbook -i <inventory> deployment/playbooks/bootstrap_jenkins_agents_docker_ctrl01.yml

Expected result:

  • Docker container jenkins-agent-ctrl-docker is running.
  • Jenkins reports node ctrl-docker as online.

3. Prove workloads run on the agent (not the controller)

Use a simple pipeline targeting the label:

pipeline {
  agent { label 'ctrl-docker' }
  stages {
    stage('validation') {
      steps {
        sh 'whoami'
        sh 'terraform version | head -n 1'
        sh 'docker version'
        sh 'docker compose version'
      }
    }
  }
}

Expected result:

  • Stage executes on the agent node.
  • Controller remains executor-less for normal operation.

Validation

  • Container is running:
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" | rg 'jenkins-agent|jenkins-controller'
  • Jenkins shows the node online (token example):
TOKEN="$(sudo sh -c 'tr -d "\n" </opt/jenkins/.secrets/admin_api_token')"
curl -g -sS -u "admin:${TOKEN}"   "http://localhost:8080/computer/api/json?tree=computer[displayName,offline]"   | head -c 800 && echo

Troubleshooting

  • Agent container restarts
    Check container logs:

    docker logs --tail 200 jenkins-agent-ctrl-docker
    

  • Node missing / JNLP endpoint returns 404
    The node was not defined. Add the node via JCasC (recommended) or provide the secret out-of-band.

  • Docker socket permissions
    If mounting /var/run/docker.sock, ensure the agent container has the socket GID as a supplemental group.


References


Maintainer: HybridOps
License: MIT-0 for code, CC-BY-4.0 for documentation