Como coletar projetos no Jenkins se você precisar de muitos ambientes diferentes

Como coletar projetos no Jenkins se você precisar de muitos ambientes diferentes

Existem muitos artigos no Habré sobre Jenkins, mas poucos descrevem exemplos de como Jenkins e agentes docker funcionam. Todas as ferramentas populares de construção de projetos, como Drone.io, Pipeline do Bitbucket, GitLab, Ações do GitHub e outros, podem recolher tudo em contentores. Mas e Jenkins?

Hoje existe uma solução para o problema: Jenkins 2 é ótimo para trabalhar com Agentes Docker. Neste artigo quero compartilhar minha experiência e mostrar como você pode fazer isso sozinho.

Por que comecei a resolver esse problema?

Já que estamos em companhia Citrônio Como usamos muitas tecnologias diferentes, temos que manter diferentes versões de Node.JS, Gradle, Ruby, JDK e outros na máquina assembly. Mas muitas vezes os conflitos de versão não podem ser evitados. Sim, você terá razão se disser que existem vários gerenciadores de versão como nvm, rvm, mas nem tudo é tão tranquilo com eles e essas soluções apresentam problemas:

  • uma grande quantidade de tempo de execução que os desenvolvedores esquecem de limpar;
  • existem conflitos entre diferentes versões dos mesmos tempos de execução;
  • Cada desenvolvedor precisa de um conjunto diferente de componentes.

Existem outros problemas, mas deixe-me falar sobre a solução.

Jenkins no Docker

Como o Docker agora está bem estabelecido no mundo do desenvolvimento, quase tudo pode ser executado usando o Docker. Minha solução é ter o Jenkins no Docker e poder executar outros contêineres do Docker. Essa pergunta começou a ser feita em 2013 no artigo “Docker agora pode ser executado dentro do Docker".

Resumindo, você só precisa instalar o próprio Docker em um contêiner funcional e montar o arquivo /var/run/docker.sock.

Aqui está um exemplo de Dockerfile criado para 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

Assim, obtivemos um contêiner Docker que pode executar comandos Docker na máquina host.

Configuração de compilação

Não muito tempo atrás, Jenkins teve a oportunidade de descrever suas regras usando Pipeline sintaxe, o que torna bastante fácil alterar o script de construção e armazená-lo no repositório.

Então vamos colocar um Dockerfile especial no próprio repositório, que conterá todas as bibliotecas necessárias para a construção. Dessa forma, o próprio desenvolvedor poderá preparar um ambiente repetível e não precisará solicitar ao OPS a instalação de uma versão específica do Node.JS no host.

FROM node:12.10.0-alpine

RUN npm install yarn -g

Esta imagem de construção é adequada para a maioria dos aplicativos Node.JS. E se, por exemplo, você precisar de uma imagem para um projeto JVM com um scanner Sonar incluído? Você é livre para escolher os componentes necessários para a montagem.

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/

Descrevemos o ambiente de montagem, mas o que Jenkins tem a ver com isso? E os agentes Jenkins podem trabalhar com essas imagens Docker e construí-las internamente.

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

Directiva agent usa propriedade dockeronde você pode especificar:

  • o nome do contêiner de montagem de acordo com sua política de nomenclatura;
  • argumentos necessários para executar o contêiner de construção, onde em nosso caso montamos o diretório atual como um diretório dentro do contêiner.

E já nas etapas de build indicamos quais comandos executar dentro do agente de build Docker. Isso pode ser qualquer coisa, então também inicio a implantação de aplicativos usando ansible.

Abaixo, quero mostrar um Jenkinsfile genérico que um aplicativo Node.JS simples pode construir.

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()
        }
    }

}

O que aconteceu?

Graças a este método, resolvemos os seguintes problemas:

  • o tempo de configuração da montagem do ambiente é reduzido para 10 a 15 minutos por projeto;
  • um ambiente de construção de aplicativos totalmente repetível, já que você pode construí-lo dessa forma em seu computador local;
  • não há problemas com conflitos entre diferentes versões de ferramentas de montagem;
  • sempre um espaço de trabalho limpo que não fica obstruído.

A solução em si é simples e óbvia e permite obter algumas vantagens. Sim, o limite de entrada aumentou um pouco em relação aos comandos simples para montagens, mas agora há a garantia de que sempre será construído e o próprio desenvolvedor poderá escolher tudo o que for necessário para seu processo de construção.

Você também pode usar a imagem que coletei Jenkins + Docker. Todas as fontes são abertas e localizadas em rmuhamedgaliev/jenkins_docker.

Ao escrever este artigo, surgiu uma discussão sobre o uso de agentes em servidores remotos para não carregar o nó mestre usando um plugin plugin docker. Mas falarei sobre isso no futuro.

Fonte: habr.com

Adicionar um comentário