Jenkins: Usando vários contêineres docker para construir e implantar um aplicativo

Jenkins: Usando vários contêineres docker para construir e implantar um aplicativo

Antecedentes: Jenkins está sendo executado dentro de um contêiner docker, o que funciona muito bem, mas por design queremos que todos os processos de construção sejam executados dentro de contêineres docker para minimizar o software instalado dentro do contêiner Jenkins.

Problema: como faço para construir um processo de três estágios usando dois contêineres docker diferentes, onde todas as três etapas compartilham arquivos?

Etapa 1: construir

  • compilação npm

Etapa 2: teste

  • teste npm`

Etapa 3: execute a implantação de código AWS

  • aws implantar push --nome do aplicativo nome do aplicativo --s3-location s3://my-bucket/nome do aplicativo --ignore-hidden-files
  • aws implantar create-deployment --nome do aplicativo nome do aplicativo --s3-location bucket=meu-bucket,key=nome do aplicativo,bundleType=zip --deployment-group-name dg

Como divido o arquivo Jenkins em vários estágios e compartilho a saída do primeiro estágio para os outros estágios?

Jenkinsfile simples de dois estágios

pipeline {
  agent {
    docker {
      image 'node:10.8.0'
    }
  }
  stages {
    stage('Build') {
      steps {
        sh 'npm install'
      }
    }
    stage('Test') {
      steps {
        sh 'npm test'
      }
    }
  }
}

Mas, quando adiciono na terceira etapa, as coisas ficam mais interessantes, já que não posso usar uma imagem docker global (agente)

pipeline {
  agent none
  stages {
    stage('Build') {
      agent {
        docker { image 'node:10.8.0' }
      }
      steps {
        sh 'npm install'
      }
    }
    stage('Test') {
      agent {
        docker { image 'node:10.8.0' }
      }
      steps {
        sh 'npm test'
      }
    }
    stage('Deploy') {
      agent {
        docker { image 'coreos/awscli' }
      }
      steps {
        sh 'echo "Deploying to AWS"'
        sh 'aws help'
      }
    }
  }
}

Acima, o 'teste npm' falha porque os resultados do estágio de construção são perdidos. E a implantação do código não funcionaria porque todos os artefatos de construção foram perdidos.

Uma solução alternativa para fazer o teste funcionar é ter um estágio 'BuildAndTest' que usa uma imagem, mas isso perde algumas das vantagens de etapas separadas.

pipeline {
  agent none
  stages {
    stage('Build And Test') {
      agent {
        docker { image 'node:10.8.0' }
      }
      steps {
        sh 'npm install'
        sh 'npm test'
      }
    }
    stage('Deploy') {
      agent {
        docker { image 'coreos/awscli' }
      }
      steps {
        sh 'echo "Deploying to AWS"'
        sh 'aws help'
      }
    }
  }
}

Uma outra solução (super feia) é criar uma imagem personalizada que tenha o node e o aws instalados, mas isso significa que toda vez que migrarmos para uma versão mais recente do node e/ou do aws, teremos que criar outra imagem docker com a versão atualizada , quando na verdade são tarefas completamente separadas.

A outra solução é montar uma imagem compartilhada entre todas as instâncias, mas como faço para criar uma imagem 'temporária' que seja compartilhada apenas para esta compilação e que seja excluída após a conclusão da compilação?

Responder1

Logo depois de postar a pergunta, encontrei um artigo de um desenvolvedor do Jenkins

https://jenkins.io/blog/2018/07/02/whats-new-declarative-piepline-13x-sequential-stages/

Isto é o que eu inventei

pipeline {
  agent none
  stages {
    stage('Build and Test') {
      agent {
        docker 'node:10.8.0'
      }
      stages {
        stage('Build') {
          steps {
            sh 'npm install'
          }
        }
        stage('Test') {
          steps {
            sh 'npm test'
          }
        }
      }
      post {
        success {
          stash name: 'artifacts', includes: "node_modules/**/*"
        }
      }
    }

    stage('Deploy') {
      agent {
        docker 'coreos/awscli'
      }
      steps {
        unstash 'artifacts'
        sh 'echo "Deploying to AWS"'
        sh 'aws help'
      }
    }
  }
}

Jenkins agora permite vários estágios dentro do declarativo, e eu não sabia sobre os comandos 'stash/unstash', que funcionam muito bem para mim.

informação relacionada