Jak tworzyć projekty w Jenkinsie, gdy potrzebne są różne środowiska

Jak tworzyć projekty w Jenkinsie, gdy potrzebne są różne środowiska

Na Habrze jest wiele artykułów o Jenkinsie, ale niewiele z nich opisuje przykład działania Jenkins i agentów Docker. Wszystkie popularne narzędzia do budowy projektów, takie jak Drone.io, Bitbucket Pipeline, GitLab, GitHub actions i inne, mogą kompilować wszystko w kontenerach. A co z Jenkins?

Dziś istnieje rozwiązanie problemu: Jenkins 2 doskonale potrafi pracować z agentami Docker.W artykule chcę podzielić się doświadczeniem i pokazać, jak możesz to zrobić samodzielnie.

Dlaczego zająłem się rozwiązaniem tego problemu?

Ponieważ w naszej firmie Citronium używamy wielu różnych technologii, więc na maszynie do budowy musimy utrzymywać różne wersje Node.js, Gradle, Ruby, JDK i innych. Jednak często nie da się uniknąć konfliktów wersji. Tak, masz rację, jeśli powiesz, że są różne menedżery wersji, takie jak nvm, rvm, ale nie wszystko z nimi jest takie proste, a te rozwiązania mają swoje problemy:

  • duża ilość środowisk uruchomieniowych, które deweloperzy zapominają czyścić;
  • są konflikty między różnymi wersjami tych samych środowisk uruchomieniowych;
  • każdemu deweloperowi potrzeba innego zestawu komponentów.

Są też inne problemy, ale lepiej opowiem o rozwiązaniu.

Jenkins w Dockerze

Ponieważ Docker jest już dobrze zakorzeniony w dziedzinie programowania, prawie wszystko można uruchomić za pomocą Dockera. Moim rozwiązaniem jest to, aby Jenkins był w Dockerze i mógł uruchamiać inne kontenery Docker. Te kwestie zaczęto poruszać już w 2013 roku w artykule „Docker może teraz działać w Dockera.«.

Mówiąc krótko, trzeba tylko zainstalować Docker w kontenerze roboczym i zamontować plik. /var/run/docker.sock.

Oto przykład Dockerfile, który udało się stworzyć dla 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

W ten sposób uzyskaliśmy kontener Docker, który może wykonywać polecenia Docker na maszynie gospodarczej.

Konfiguracja budowy

Niedawno Jenkins zyskał możliwość opisywania swoich reguł przy pomocy Pipeline składni, co pozwala dość łatwo zmieniać skrypt budowy i przechowywać go w repozytorium.

Umieśćmy w repozytorium specjalny Dockerfile, który zawiera wszystkie niezbędne biblioteki do budowy. Dzięki temu deweloper może stworzyć powtarzalne środowisko i nie będzie musiał prosić OPS o zainstalowanie na hoście określonej wersji Node.JS.

FROM node:12.10.0-alpine

RUN npm install yarn -g

Taki obraz budowy nadaje się do większości aplikacji Node.JS. A co jeśli potrzebujesz obrazu dla projektu JVM z wbudowanym skanerem Sonar? Możesz samodzielnie wybrać potrzebne komponenty do budowy.

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/

Opisaliśmy środowisko budowy, ale co ma z tym wspólnego Jenkins? Agenci Jenkinsa potrafią pracować z takimi obrazami Docker i przeprowadzać budowę w ich wnętrzu.

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

Dyrektywa agent używa właściwości docker, gdzie możesz określić:

  • nazwę kontenera budowlanego zgodnie z twoją polityką nazewnictwa;
  • argumenty potrzebne do uruchomienia kontenera budowlanego, gdzie w naszym przypadku montujemy bieżący katalog jako katalog wewnątrz kontenera.

A w krokach budowy wskazujemy, jakie komendy mają być wykonane wewnątrz agenta Docker do budowy. Może to być wszystko, w ten sposób również uruchamiam wdrożenie aplikacji z pomocą ansible.

Poniżej chciałbym przedstawić ogólny Jenkinsfile, który może zbudować prostą aplikację Node.JS.

def DOCKER_IMAGE_BRANCH = ""
def GIT_COMMIT_HASH = ""

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

    agent any

    stages {

        stage("Przygotuj obraz do budowy") {
            steps {
                sh "docker build -f Dockerfile.build . -t project-build:${DOCKER_IMAGE_BRANCH}"
            }
        }

        stage("Zbuduj 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()
        }
    }

}

Co z tego wynikło?

Dzięki temu rozwiązaniu udało się nam rozwiązać następujące problemy:

  • czas konfiguracji środowiska budowy wynosi 10–15 minut na projekt;
  • pełne powtarzalne środowisko budowy aplikacji, ponieważ można to robić również na lokalnym komputerze;
  • brak problemów z konfliktami różnych wersji narzędzi budowlanych;
  • zawsze czysty workspace, który nie jest zaśmiecony.

Rozwiązanie jest proste i oczywiste oraz przynosi same korzyści. Tak, próg wejścia jest trochę wyższy w porównaniu do prostych poleceń budowlanych, ale teraz mamy gwarancję, że zawsze będzie budowane i programista sam może wybrać wszystko, co potrzebne do jego procesu budowy.

Możesz również skorzystać z utworzonego przeze mnie obrazu Jenkins + Docker. Wszystkie źródła są otwarte i dostępne na rmuhamedgaliev\/jenkins_docker.

W trakcie pisania artykułu wywiązała się dyskusja na temat używania agentów na zdalnych serwerach, aby nie obciążać głównej nodu za pomocą wtyczki docker-plugin. Ale o tym opowiem w przyszłości.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster