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

imagem


Existem muitos artigos sobre Habré sobre Jenkins, mas poucos exemplos do trabalho de Jenkins e de agentes estivadores são descritos. Todas as ferramentas populares de criação de projetos, como as ações Drone.io , Bitbucket Pipeline , GitLab , GitHub e outras, podem coletar tudo em contêineres. Mas e Jenkins?


Hoje existe uma solução para o problema: o Jenkins 2 é ótimo em trabalhar com agentes do Docker . No artigo, quero compartilhar experiências e mostrar como você pode fazer isso sozinho.


Por que eu resolvi esse problema?


Como nós da Citronium usamos muitas tecnologias diferentes, precisamos manter diferentes versões do Node.JS, Gradle, Ruby, JDK e outras na máquina de montagem. Mas muitas vezes conflitos de versão não podem ser evitados. Sim, você estará certo se disser que existem vários gerenciadores de versão como nvm, rvm, mas nem tudo é tão fácil com eles e essas soluções têm problemas:


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

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


Jenkins em Docker


Como o Docker agora está bem enraizado no setor de desenvolvimento, quase tudo pode ser iniciado usando o Docker. Minha solução é que Jenkins esteja no Docker e possa executar outros contêineres do Docker. Esta pergunta começou a ser feita em 2013 no artigo "O Docker agora pode ser executado no Docker ".


Em resumo, basta instalar o Docker no contêiner de trabalho e montar o arquivo /var/run/docker.sock .


Aqui está um exemplo do Dockerfile lançado para Jenkins.


 FROM jenkins/jenkins:lts ARG DOCKER_COMPOSE_VERSION=1.25.0 USER root RUN apt-get update && \ apt-get upgrade -y && \ 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 && \ apt-get clean autoclean && apt-get autoremove && rm -rf /var/lib/{apt,dpkg,cache,log}/ RUN curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose RUN usermod -aG docker jenkins && gpasswd -a jenkins docker USER jenkins 

Portanto, temos um contêiner Docker que pode executar comandos do Docker na máquina host.


Configuração de compilação


Há pouco tempo, Jenkins teve a oportunidade de descrever suas regras usando a sintaxe Pipeline , que permite 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 da biblioteca. Portanto, o próprio desenvolvedor pode preparar um ambiente repetível e o OPS não precisará ser solicitado a colocar uma versão específica do Node.JS no host.


 FROM node:12.10.0-alpine RUN npm install yarn -g 

Essa 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 incluído dentro do Sonar? Você é livre para escolher os componentes que precisa construir.


 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 construção, mas o que Jenkins tem a ver com isso? E os agentes da Jenkins podem trabalhar com essas imagens do Docker e criar dentro.


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

A diretiva do agent usa a propriedade docker , na qual você pode especificar:


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

Jenkins


E já nas etapas de montagem, indicamos quais comandos executar dentro do agente do Docker de montagem. Ele pode fazer qualquer coisa, então eu também executo a implantação do aplicativo usando ansible.


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


 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;
  • ambiente completamente repetitivo do conjunto do aplicativo, pois ele também pode ser montado no computador local;
  • sem conflitos com diferentes versões de ferramentas de montagem;
  • sempre um espaço de trabalho limpo que não fique entupido.

A solução em si é simples e óbvia e permite que você obtenha algumas vantagens. Sim, o limite de entrada aumentou um pouco em comparação com os comandos de construção simples, mas agora há uma garantia de que sempre será coletado e o próprio desenvolvedor poderá escolher tudo o que for necessário para o processo de construção.


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


Durante a redação do artigo, houve uma discussão sobre o uso de agentes em servidores remotos para não carregar o nó principal usando o docker-plugin . Mas vou falar sobre isso no futuro.

Source: https://habr.com/ru/post/pt481466/


All Articles