Jenkins: 複数の Docker コンテナを使用してアプリケーションを構築およびデプロイする

Jenkins: 複数の Docker コンテナを使用してアプリケーションを構築およびデプロイする

背景: Jenkins は Docker コンテナ内で実行されており、問題なく動作しますが、設計上、すべてのビルド プロセスを Docker コンテナ内で実行して、Jenkins コンテナ内にインストールされるソフトウェアを最小限に抑える必要があります。

問題: 2 つの異なる Docker コンテナを使用して、3 つのステップすべてでファイルを共有する 3 段階のプロセスを構築するにはどうすればよいですか?

ステップ1: 構築

  • npmビルド

ステップ2: テスト

  • npm テスト`

ステップ3: AWSコードデプロイを実行する

  • aws deploy push --application-name app-name --s3-location s3://my-bucket/app-name --ignore-hidden-files
  • aws deploy create-deployment --application-name app-name --s3-location bucket=my-bucket,key=app-name,bundleType=zip --deployment-group-name dg

Jenkins ファイルを複数のステージに分割し、最初のステージの出力を他のステージで共有するにはどうすればよいですか?

シンプルな2段階のJenkinsfile

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

しかし、第3段階を追加すると、グローバルDockerイメージ(エージェント)を使用できなくなるため、状況はさらに面白くなります。

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

上記では、ビルド ステージの結果が失われているため、 'npm test' は失敗します。また、ビルド成果物がすべて失われているため、コード デプロイは機能しません。

テストを機能させるための回避策の 1 つは、イメージを使用する「BuildAndTest」ステージを用意することですが、これにより個別のステップの利点の一部が失われます。

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

もう 1 つの (非常に醜い) 解決策は、node と aws の両方がインストールされたカスタム イメージを作成することですが、これは、node または aws のいずれかの新しいバージョンに移行するたびに、更新されたバージョンで別の docker イメージを作成する必要があることを意味し、実際にはこれらは完全に別のタスクです。

他の解決策は、すべてのインスタンス間で共有イメージをマウントすることですが、このビルドでのみ共有され、ビルドの完了後に削除される「一時」イメージを作成するにはどうすればよいでしょうか?

答え1

質問を投稿した直後に、Jenkins開発者の記事を見つけました

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

これが私が思いついたものです

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 では宣言内で複数のステージが許可されるようになりましたが、私にとっては非常に便利な「stash/unstash」コマンドについては知りませんでした。

関連情報