Sådan opbygges projekter i Jenkins, når mange forskellige miljøer er nødvendige

Sådan opbygges projekter i Jenkins, når mange forskellige miljøer er nødvendige

Der er mange artikler om Jenkins på Habr, men sjældent beskrives et eksempel på, hvordan Jenkins og Docker-agenter fungerer. Alle populære projektbyggeværktøjer som Drone.io, Bitbucket Pipeline, GitLab, GitHub actions og andre kan samle alt i containere. Men hvad med Jenkins?

I dag er der en løsning på problemet: Jenkins 2 fungerer fremragende med Docker-agenter. I denne artikel vil jeg dele mine erfaringer og vise, hvordan du kan gøre det selv.

Hvorfor begyndte jeg at løse dette problem?

Da vi i virksomheden Citronium bruger mange forskellige teknologier, er det nødvendigt for byggeværktøjet at have forskellige versioner af Node.JS, Gradle, Ruby, JDK og andre. Men oftest er der uundgåelige versionskonflikter. Ja, du har ret, hvis du siger, at der findes forskellige versionsadministrationsværktøjer som nvm, rvm, men det er ikke så glat med dem, og disse løsninger har deres problemer:

  • et stort volumen af runtime-miljøer, som udviklerne glemmer at rydde op;
  • der er konflikter mellem forskellige versioner af de samme runtime-miljøer;
  • hver udvikler har brug for et forskelligt sæt af komponenter.

Der er også andre problemer, men lad mig hellere fortælle om løsningen.

Jenkins i Docker

Da Docker nu er godt etableret inden for udvikling, kan næsten alt køres ved hjælp af Docker. Min løsning er, at Jenkins skal køre i Docker og være i stand til at starte andre Docker-containere. Dette spørgsmål blev rejst allerede i 2013 i artiklen "Docker can now run within Docker«.

Kort sagt, er det nødvendigt at installere Docker i containeren og montere filen /var/run/docker.sock.

Her er et eksempel på Dockerfile, som vi har lavet til Jenkins.

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

På denne måde fik vi en Docker-container, der kan udføre Docker-kommandoer på værtsmaskinen.

Konfiguration af bygning

For nylig fik Jenkins muligheden for at beskrive sine regler ved hjælp af Pipeline syntaks, som gør det relativt simpelt at ændre bygge-scriptet og opbevare det i et repository.

Lad os placere en særlig Dockerfile i selve depotet, som vil indeholde alle de nødvendige biblioteker til opbygning. På den måde kan udvikleren forberede et gentageligt miljø, og der er ikke behov for at anmode OPS om at installere en bestemt version af Node.JS på værten.

FROM node:12.10.0-alpine

RUN npm install yarn -g

Denne byggeimage er passende til de fleste Node.JS-applikationer. Men hvis du for eksempel har brug for en image til et JVM-projekt med Sonar-scanneren inkluderet? Du er fri til at vælge de nødvendige komponenter til opbygning.

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/

Vi har beskrevet byggeomgivelserne, men hvad har Jenkins med det at gøre? Jenkins-agenter kan arbejde med sådanne Docker-images og udføre opbygning indeni.

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

Direktiv agent bruger egenskaben docker, hvor du kan angive:

  • navnet på byggecontaineren i henhold til din navngivningspolitik;
  • de nødvendige argumenter til at køre byggecontaineren, hvor vi i vores tilfælde monterer den nuværende mappe som en mappe inde i containeren.

Og i bygge-trinnene angiver vi, hvilke kommandoer der skal udføres inde i bygge-Docker-agenten. Det kan være hvad som helst, på den måde kan jeg også udføre deployment af applikationer ved hjælp af Ansible.

Her vil jeg vise et generelt Jenkinsfile, der kan samle en simpel Node.JS-applikation.

def DOCKER_IMAGE_BRANCH = ""
def GIT_COMMIT_HASH = ""

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

    agent any

    stages {

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

        stage("Byg projekt") {
            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()
        }
    }

}

Hvad er resultatet?

Takket være denne metode har vi løst følgende problemer:

  • tiden til at konfigurere build-omgivelser reduceres til 10-15 minutter pr. projekt;
  • et helt reproducerbart bygget miljø for applikationen, da det også kan bygges på den lokale computer;
  • der er ingen problemer med konflikter mellem forskellige versioner af build-værktøjer;
  • altid et rent arbejdsrum, som ikke bliver fyldt op.

Selve løsningen er simpel og indlysende og giver kun fordele. Ja, indgangsbarrieren er en smule højere sammenlignet med simple build-kommandoer, men nu er der garanti for, at det altid vil blive bygget, og udvikleren kan selv vælge alt, hvad der er nødvendigt for hans build-proces.

Du kan også bruge det billede, jeg har samlet Jenkins + Docker. Alle kilder er åbne og ligger på rmuhamedgaliev\/jenkins_docker.

Under skrivningen af artiklen opstod der en diskussion om brugen af agenter på fjernservere for ikke at belaste master-noden ved hjælp af pluginet docker-plugin. Men det vil jeg fortælle om i fremtiden.

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster