Code Monkey home page Code Monkey logo

jenkins-agent-dind's Introduction

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.
  • 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'
      }
    }
  }
}

jenkins-agent-dind's People

Contributors

felipecrs avatar dependabot[bot] avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.