Skip to content

A full fledged Docker in Docker image to act as a Jenkins Agent.

License

Notifications You must be signed in to change notification settings

mehdiakar/jenkins-agent-dind

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Jenkins Agent with Docker in Docker

CI Docker Pulls Docker Image Size

A full fledged Docker in Docker image to act as a Jenkins Agent. Based on buildpack-deps:focal, it is a mashup of jenkins/inbound-agent with docker:dind.

Features

  • Based on Ubuntu 20.04 Focal Fossa: a more common OS to run your builds.
  • From buildpack-deps: a image with many common dependencies installed, run your builds without hassle.
  • It contains the latest release of agent.jar: even more up-to-date than jenkins/agent itself.
  • Fully working Docker in Docker: run your docker build commands with no intervention and share of resources between the host.
  • Act just as a Jenkins Agent out-of-the-box: run ephemeral build containers by using Docker Plugin (or Kubernetes Plugin) for Jenkins. Works as the official jnlp/inbound-agent.

Usage

Command line

Spin this agent in shell, if you want to play with it:

# -it: allows to interact with the container
# --rm: removes the container and its volumes after exiting
# --privileged: needed for running Docker in Docker
docker run -it --rm --privileged ghcr.io/felipecrs/jenkins-agent-dind bash

Agent Template in Docker Cloud configuration on Jenkins

Sample Agent Template configuration

Kubernetes Plugin Pod Template

The following is the Pod definition that you can use as a Pod template with the Kubernetes Plugin.

apiVersion: v1
kind: Pod
spec:
  containers:
    - name: jnlp
      image: ghcr.io/felipecrs/jenkins-agent-dind:latest
      imagePullPolicy: Always
      securityContext:
        privileged: true
      workingDir: /home/jenkins/agent
      volumeMounts:
        - mountPath: /home/jenkins/agent
          name: workspace-volume
      terminationMessagePolicy: FallbackToLogsOnError
  hostNetwork: false
  automountServiceAccountToken: false
  enableServiceLinks: false
  dnsPolicy: Default
  restartPolicy: Never
  terminationGracePeriodSeconds: 30
  volumes:
    - name: workspace-volume
      emptyDir: {}

As a Jenkinsfile docker agent

When running as a Jenkinsfile docker agent, Jenkins will run the container as the host user instead of the default jenkins user.

But this image comes with fixuid, which will automatically fix the user and group IDs of the jenkins user that comes with the image to match the host user.

This ensures file permissions are correct when running as a Jenkinsfile docker agent, as well as ensures docker from within the container still works.

pipeline {
  agent {
    docker {
      image 'ghcr.io/felipecrs/jenkins-agent-dind:latest'
      alwaysPull true
      // --rm: ensures the container volumes are removed after the build
      // --group-add=docker: is needed when using docker exec to run commands,
      // which is what Jenkins does when running as a Jenkinsfile docker agent
      args '--rm --privileged --group-add=docker'
    }
  }
  stages {
    stage('Verify docker works') {
      steps {
        sh 'docker version'
      }
    }
  }
}

Accessing the image through SSH

The image comes with SSHD installed and configured, but it does not start by default. To enable it, you need to add the SSHD_ENABLED=true environment variable when running the container.

The SSHD server will run on port 22 and you can use the jenkins user to login, without any password.

Automatically expose SSH access for all builds

The image comes with a convenience script at /ssh-command/get.sh that will output the SSH command to connect to the container, which you can use to connect to the container through SSH. Example:

Example of SSH command

Using Kubernetes Plugin

You can use a Kubernetes Pod Template to automatically expose SSH access for all builds.

First you'll need to have dynamic-hostports installed in your cluster. You can install it with the following command:

kubectl apply -f https://raw.githubusercontent.com/felipecrs/jenkins-agent-dind/master/dynamic-hostports.yaml

Then you can use the following Pod Template:

apiVersion: v1
kind: Pod
metadata:
  labels:
    dynamic-hostports: "22"
spec:
  containers:
    - name: jnlp
      image: ghcr.io/felipecrs/jenkins-agent-dind:{{ $agentTag }}
      imagePullPolicy: Always
      env:
        - name: SSHD_ENABLED
          value: "true"
      ports:
        - containerPort: 22
      securityContext:
        privileged: true
      workingDir: /home/jenkins/agent
      volumeMounts:
        - mountPath: /home/jenkins/agent
          name: workspace-volume
        - name: podinfo
          mountPath: /ssh-command/podinfo
      terminationMessagePolicy: FallbackToLogsOnError
  hostNetwork: false
  automountServiceAccountToken: false
  enableServiceLinks: false
  restartPolicy: Never
  terminationGracePeriodSeconds: 30
  volumes:
    - name: workspace-volume
      emptyDir: {}
    - name: podinfo
      downwardAPI:
        items:
          - path: "sshd-port"
            fieldRef:
              fieldPath: metadata.annotations['dynamic-hostports.k8s/22']
          - path: "node-fqdn"
            fieldRef:
              fieldPath: metadata.annotations['dynamic-hostports.k8s/node-fqdn']

And here is an example of a Jenkinsfile:

pipeline {
  agent any
  options {
    ansiColor('xterm')
  }
  stages {
    stage ('Get SSH command') {
      steps {
        sh '/ssh-command/get.sh'
      }
    }
  }
}

It also works if you use a nested Docker agent:

pipeline {
  agent {
    docker {
      image 'felipecrs/fixdockergid:latest'
      args '--volume=/ssh-command:/ssh-command --volume=/var/run/docker.sock:/var/run/docker.sock --group-add=docker'
    }
  }
  options {
    ansiColor('xterm')
  }
  stages {
    stage ('Get SSH command') {
      steps {
        sh '/ssh-command/get.sh'
      }
    }
  }
}
Using as a Jenkinsfile docker agent
// Generate an "unique" port for SSHD
env.SSHD_PORT = new Random(env.BUILD_TAG.hashCode()).nextInt(23000 - 22000) + 22000

pipeline {
  agent {
    agent {
      docker {
        image 'ghcr.io/felipecrs/jenkins-agent-dind:latest'
        args "--privileged --group-add=docker --env=SSHD_ENABLED=true --publish=${env.SSHD_PORT}:22"
      }
    }
  }
  options {
    ansiColor('xterm')
  }
  stages {
    stage ('Get SSH command') {
      steps {
        sh '/ssh-command/get.sh'
      }
    }
  }
}

About

A full fledged Docker in Docker image to act as a Jenkins Agent.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Dockerfile 67.0%
  • Shell 33.0%