So sammeln Sie Projekte in Jenkins, wenn Sie viele verschiedene Umgebungen benötigen

So sammeln Sie Projekte in Jenkins, wenn Sie viele verschiedene Umgebungen benötigen

Auf Habré gibt es viele Artikel über Jenkins, aber nur wenige beschreiben Beispiele für die Funktionsweise von Jenkins und Docker-Agenten. Alle gängigen Projekterstellungstools wie Drone.io, Bitbucket-Pipeline, Gitlab, GitHub-Aktionen und andere können alles in Behältern sammeln. Aber was ist mit Jenkins?

Heute gibt es eine Lösung für das Problem: Mit Jenkins 2 lässt sich hervorragend arbeiten Docker-Agenten. In diesem Artikel möchte ich meine Erfahrungen teilen und zeigen, wie man es selbst machen kann.

Warum habe ich angefangen, dieses Problem zu lösen?

Da wir in Gesellschaft sind Citronium Da wir viele verschiedene Technologien verwenden, müssen wir unterschiedliche Versionen von Node.JS, Gradle, Ruby, JDK und anderen auf der Assembly-Maschine vorhalten. Doch oft lassen sich Versionskonflikte nicht vermeiden. Ja, Sie werden Recht haben, wenn Sie sagen, dass es verschiedene Versionsmanager wie NVM, RVM gibt, aber bei denen läuft nicht alles so reibungslos und diese Lösungen haben Probleme:

  • eine große Menge an Laufzeit, die Entwickler vergessen zu bereinigen;
  • es gibt Konflikte zwischen verschiedenen Versionen derselben Laufzeiten;
  • Jeder Entwickler benötigt einen anderen Satz an Komponenten.

Es gibt noch andere Probleme, aber lassen Sie mich Ihnen die Lösung erläutern.

Jenkins in Docker

Da Docker mittlerweile in der Entwicklungswelt gut etabliert ist, kann fast alles mit Docker ausgeführt werden. Meine Lösung besteht darin, Jenkins in Docker zu haben und andere Docker-Container ausführen zu können. Diese Frage wurde bereits 2013 in dem Artikel „Docker kann jetzt innerhalb von Docker ausgeführt werden«.

Kurz gesagt, Sie müssen lediglich Docker selbst in einem funktionierenden Container installieren und die Datei mounten /var/run/docker.sock.

Hier ist eine Beispiel-Dockerdatei, die 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

Somit haben wir einen Docker-Container erhalten, der Docker-Befehle auf dem Host-Computer ausführen kann.

Build-Setup

Vor nicht allzu langer Zeit hatte Jenkins die Gelegenheit, seine Regeln anhand von zu beschreiben Pipeline Syntax, die es ganz einfach macht, das Build-Skript zu ändern und im Repository zu speichern.

Legen wir also eine spezielle Docker-Datei im Repository selbst ab, die alle für den Build erforderlichen Bibliotheken enthält. Auf diese Weise kann der Entwickler selbst eine wiederholbare Umgebung vorbereiten und muss OPS nicht bitten, eine bestimmte Version von Node.JS auf dem Host zu installieren.

FROM node:12.10.0-alpine

RUN npm install yarn -g

Dieses Build-Image ist für die meisten Node.JS-Anwendungen geeignet. Was ist, wenn Sie beispielsweise ein Bild für ein JVM-Projekt benötigen, in dem ein Sonar-Scanner enthalten ist? Die Auswahl der Komponenten, die Sie für die Montage benötigen, ist Ihnen freigestellt.

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 die Assembly-Umgebung beschrieben, aber was hat Jenkins damit zu tun? Und Jenkins-Agenten können mit solchen Docker-Images arbeiten und sie intern erstellen.

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"
    }
}

Richtlinie agent nutzt Eigentum dockerwo Sie angeben können:

  • der Name des Assembly-Containers gemäß Ihrer Benennungsrichtlinie;
  • Argumente, die zum Ausführen des Build-Containers erforderlich sind, wobei wir in unserem Fall das aktuelle Verzeichnis als Verzeichnis innerhalb des Containers bereitstellen.

Und bereits in den Build-Schritten geben wir an, welche Befehle innerhalb des Docker-Build-Agenten ausgeführt werden sollen. Das kann alles sein, daher starte ich die Anwendungsbereitstellung auch mit Ansible.

Im Folgenden möchte ich eine generische Jenkins-Datei zeigen, die eine einfache Node.JS-Anwendung erstellen kann.

def DOCKER_IMAGE_BRANCH = ""
def GIT_COMMIT_HASH = ""

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

    agent any

    stages {

        stage("Prepare build image") {
            steps {
                sh "docker build -f Dockerfile.build . -t project-build:${DOCKER_IMAGE_BRANCH}"
            }
        }

        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"
            }
        }

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

}

Was ist passiert?

Dank dieser Methode haben wir die folgenden Probleme gelöst:

  • Die Konfigurationszeit für die Umgebungsmontage wird auf 10 bis 15 Minuten pro Projekt reduziert.
  • eine vollständig wiederholbare Anwendungserstellungsumgebung, da Sie sie auf diese Weise auf Ihrem lokalen Computer erstellen können;
  • es gibt keine Probleme mit Konflikten zwischen verschiedenen Versionen von Montagewerkzeugen;
  • Immer ein sauberer Arbeitsplatz, der nicht verstopft.

Die Lösung selbst ist einfach und offensichtlich und ermöglicht Ihnen einige Vorteile. Ja, die Einstiegsschwelle ist im Vergleich zu einfachen Befehlen für Assemblys etwas gestiegen, aber jetzt gibt es eine Garantie, dass immer gebaut wird und der Entwickler selbst alles auswählen kann, was für seinen Build-Prozess notwendig ist.

Sie können auch das von mir gesammelte Bild verwenden Jenkins + Docker. Alle Quellen sind offen und befinden sich unter rmuhamedgaliev/jenkins_docker.

Beim Schreiben dieses Artikels entstand eine Diskussion über die Verwendung von Agenten auf Remote-Servern, um den Masterknoten nicht über ein Plugin zu laden Docker-Plugin. Aber darüber werde ich in Zukunft sprechen.

Source: habr.com

Kommentar hinzufügen