Wie man Projekte in Jenkins sammelt, wenn viele verschiedene Umgebungen benötigt werden

Wie man Projekte in Jenkins sammelt, wenn viele verschiedene Umgebungen benötigt werden

Es gibt viele Artikel über Jenkins auf Habr, aber nur wenige beschreiben ein Beispiel für die Arbeit mit Jenkins und Docker-Agenten. Alle beliebten Tools zur Projektbuild-Erstellung, wie Drone.io, Bitbucket Pipeline, GitLab, GitHub-Aktionen und andere, können alles in Containern bauen. Aber wie steht es um Jenkins?

Heute gibt es eine Lösung für dieses Problem: Jenkins 2 kann hervorragend mit Docker-Agentenarbeiten. In diesem Artikel möchte ich meine Erfahrungen teilen und zeigen, wie Sie das selbst machen können.

Warum habe ich mich mit der Lösung dieses Problems beschäftigt?

Da wir in der Firma Citronium viele verschiedene Technologien nutzen, müssen auf der Build-Maschine unterschiedliche Versionen von Node.JS, Gradle, Ruby, JDK und anderen ausgestattet werden. Oft sind Versionskonflikte unvermeidbar. Ja, Sie haben recht, wenn Sie sagen, dass es verschiedene Versionsmanager wie nvm, rvm gibt, aber so einfach ist es damit nicht und diese Lösungen haben ihre Probleme:

  • ein großer Umfang an Runtimes, die Entwickler vergessen zu bereinigen;
  • es gibt Konflikte zwischen verschiedenen Versionen der gleichen Runtimes;
  • jeder Entwickler benötigt eine andere Sammlung von Komponenten.

Es gibt auch andere Probleme, aber lassen Sie mich besser über die Lösung sprechen.

Jenkins in Docker

Da Docker mittlerweile gut in der Entwicklungswelt verankert ist, kann fast alles mit Docker gestartet werden. Meine Lösung besteht darin, Jenkins in Docker zu betreiben und andere Docker-Container zu starten. Diese Frage wurde bereits 2013 in dem Artikel „Docker can now run within Docker«.

diskutiert. Kurz gesagt, es ist notwendig, Docker im Arbeitscontainer zu installieren und die Datei zu mounten. /var/run/docker.sock.

Hier ist ein Beispiel für das Dockerfile, das für Jenkins erstellt wurde.

FROM jenkins/jenkins:lts

USER root

RUN apt-get update && 

apt-get -y install apt-transport-https 
     ca-certificates 
     curl 
     gnupg2 
     git 
     software-properties-common && 
curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg > /tmp/dkey; apt-key add /tmp/dkey && 
add-apt-repository 
   "deb [arch=amd64] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") 
   $(lsb_release -cs) 
   stable" && 
apt-get update && 
apt-get -y install docker-ce && 
usermod -aG docker jenkins

RUN curl -L https://github.com/docker/compose/releases/download/1.25.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose 

RUN apt-get clean autoclean && apt-get autoremove --yes && rm -rf /var/lib/{apt,dpkg,cache,log}/

USER jenkins

Auf diese Weise haben wir einen Docker-Container erhalten, der Docker-Befehle auf der Hostmaschine ausführen kann.

Build-Einrichtung

Vor nicht allzu langer Zeit gab Jenkins die Möglichkeit, seine Regeln mithilfe von Pipeline Syntax zu beschreiben, was es relativ einfach macht, das Build-Skript zu ändern und es im Repository zu speichern.

Lassen Sie uns also eine spezielle Dockerfile in das Repository einfügen, die alle notwendigen Bibliotheken für den Build enthält. So kann der Entwickler eine wiederholbare Umgebung vorbereiten, und es ist nicht notwendig, OPS um die Installation einer bestimmten Version von Node.JS auf dem Host zu bitten.

FROM node:12.10.0-alpine

RUN npm install yarn -g

Dieses Build-Image eignet sich für die meisten Node.JS-Anwendungen. Und wenn Sie zum Beispiel ein Image für ein JVM-Projekt mit einem integrierten Sonar-Scanner benötigen? Sie können selbst die notwendigen Komponenten für den Build auswählen.

FROM adoptopenjdk/openjdk12:latest

RUN apt update 
    && apt install -y 
        bash unzip wget

RUN mkdir -p /usr/local/sonarscanner 
    && cd /usr/local/sonarscanner 
    && wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-3.3.0.1492-linux.zip 
    && unzip sonar-scanner-cli-3.3.0.1492-linux.zip 
    && mv sonar-scanner-3.3.0.1492-linux/* ./ 
    && rm sonar-scanner-cli-3.3.0.1492-linux.zip 
    && rm -rf sonar-scanner-3.3.0.1492-linux 
    && ln -s /usr/local/sonarscanner/bin/sonar-scanner /usr/local/bin/sonar-scanner

ENV PATH $PATH:/usr/local/sonarscanner/bin/
ENV SONAR_RUNNER_HOME /usr/local/sonarscanner/bin/

Wir haben das Build-Umfeld beschrieben, aber was hat Jenkins damit zu tun? Jenkins-Agenten können mit solchen Docker-Images arbeiten und den Build innerhalb durchführen.

stage("Build project") {
    agent {
        docker {
            image "project-build:${DOCKER_IMAGE_BRANCH}"
            args "-v ${PWD}:/usr/src/app -w /usr/src/app"
            reuseNode true
            label "build-image"
        }
    }
    steps {
        sh "yarn"
        sh "yarn build"
    }
}

Direktive agent verwendet eine Eigenschaft docker, wo Sie angeben können:

  • den Namen des Build-Containers gemäß Ihrer Namensrichtlinie;
  • Argumente, die zum Starten des Build-Containers erforderlich sind, wo wir in unserem Fall das aktuelle Verzeichnis als Verzeichnis innerhalb des Containers mounten.

Und bereits in den Build-Schritten geben wir an, welche Befehle im Build-Docker-Agenten ausgeführt werden sollen. Das kann alles Mögliche sein, so starte ich auch die Bereitstellung von Anwendungen mit Hilfe von Ansible.

Unten möchte ich ein allgemeines Jenkinsfile zeigen, das ein einfaches Node.JS-Anwendung bauen kann.

def DOCKER_IMAGE_BRANCH = ""
def GIT_COMMIT_HASH = ""

pipeline { 
    options {
        buildDiscarder(
            logRotator(
                artifactDaysToKeepStr: "",
                artifactNumToKeepStr: "",
                daysToKeepStr: "",
                numToKeepStr: "10"
            )
        )
        disableConcurrentBuilds()
    }

    agent any

    stages {

        stage("Build-Image vorbereiten") {
            steps {
                sh "docker build -f Dockerfile.build . -t project-build:${DOCKER_IMAGE_BRANCH}"
            }
        }

        stage("Projekt bauen") {
            agent {
                docker {
                    image "project-build:${DOCKER_IMAGE_BRANCH}"
                    args "-v ${PWD}:\/usr\/src\/app -w \/usr\/src\/app"
                    reuseNode true
                    label "build-image"
                }
            }
            steps {
                sh "yarn"
                sh "yarn build"
            }
        }

    post {
        always {
            step([$class: "WsCleanup"])
            cleanWs()
        }
    }

}

Was ist das Ergebnis?

Durch diese Methode haben wir folgende Probleme gelöst:

  • Die Konfigurationszeit für die Umgebung beträgt 10 bis 15 Minuten pro Projekt;
  • vollständig reproduzierbare Bauumgebungen für Anwendungen, da man auch lokal so bauen kann;
  • keine Probleme mit Konflikten zwischen verschiedenen Versionen von Build-Tools;
  • immer ein sauberer Workspace, der sich nicht aufstaut.

Die Lösung selbst ist einfach und offensichtlich und bringt nur Vorteile. Ja, die Einstiegshürde ist etwas höher im Vergleich zu einfachen Build-Befehlen, aber dafür gibt es jetzt die Garantie, dass immer gebaut wird, und der Entwickler kann alles, was für seinen Build-Prozess notwendig ist, selbst wählen.

Außerdem können Sie das von mir erstellte Image verwenden Jenkins + Docker. Alle Quellcodes sind offen und liegen bei rmuhamedgaliev\/jenkins_docker.

Im Verlauf des Schreibens des Artikels gab es eine Diskussion über die Verwendung von Agenten auf entfernten Servern, um die Master-Node nicht mit dem Plugin zu belasten. docker-plugin. Aber darüber werde ich in Zukunft berichten.

Quelle: habr.com

60GB SSD 8Gb DDR4