Jenkins: Verwenden mehrerer Docker-Container zum Erstellen und Bereitstellen einer Anwendung

Jenkins: Verwenden mehrerer Docker-Container zum Erstellen und Bereitstellen einer Anwendung

Hintergrund: Jenkins läuft in einem Docker-Container, was gut funktioniert, aber wir möchten, dass alle Build-Prozesse standardmäßig in Docker-Containern ausgeführt werden, um die im Jenkins-Container installierte Software zu minimieren.

Problem: Wie erstelle ich einen dreistufigen Prozess mit zwei verschiedenen Docker-Containern, bei dem alle drei Schritte Dateien gemeinsam nutzen?

Schritt 1: Erstellen

  • NPM-Build - Ein Leitfaden für Entwickler

Schritt 2: Testen

  • npm-Test`

Schritt 3: AWS Code-Deploy ausführen

  • aws deploy push --Anwendungsname App-Name --S3-Standort s3://mein-Bucket/App-Name --ignore-hidden-files
  • aws deploy create-deployment --Anwendungsname App-Name --S3-Standort Bucket=mein Bucket, Schlüssel=App-Name, BundleType=Zip --Bereitstellungsgruppenname dg

Wie teile ich die Jenkins-Datei in mehrere Phasen auf und gebe die Ausgabe der ersten Phase an die anderen Phasen weiter?

Einfaches zweistufiges Jenkinsfile

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

Aber wenn ich die dritte Phase hinzufüge, wird es interessanter, da ich kein globales Docker-Image (Agent) verwenden kann.

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

Im obigen Beispiel schlägt der npm-Test fehl, da die Ergebnisse der Build-Phase verloren gehen. Und die Codebereitstellung würde nicht funktionieren, da alle Build-Artefakte verloren gehen.

Eine Problemumgehung, um den Test zum Laufen zu bringen, besteht darin, eine „BuildAndTest“-Phase zu haben, die ein Image verwendet. Dadurch gehen jedoch einige der Vorteile separater Schritte verloren.

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

Eine andere (sehr hässliche) Lösung besteht darin, ein benutzerdefiniertes Image zu erstellen, auf dem sowohl Node als auch AWS installiert sind. Das bedeutet aber, dass wir jedes Mal, wenn wir auf eine neuere Version von Node und/oder AWS migrieren, ein weiteres Docker-Image mit der aktualisierten Version erstellen müssen, obwohl es sich in Wirklichkeit um völlig unterschiedliche Aufgaben handelt.

Die andere Lösung besteht darin, ein gemeinsames Image für alle Instanzen bereitzustellen. Wie erstelle ich jedoch ein „temporäres“ Image, das nur für diesen Build gemeinsam genutzt wird und nach Abschluss des Builds gelöscht wird?

Antwort1

Gleich nachdem ich die Frage gepostet hatte, fand ich einen Artikel von einem Jenkins-Entwickler

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

Das ist, was mir eingefallen ist

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 ermöglicht jetzt mehrere Phasen innerhalb der Deklaration, und ich kannte die Befehle „stash/unstash“ nicht, die bei mir hervorragend funktionieren.

verwandte Informationen