Jenkinsでdockerコンテナを利用したビルドでハマった問題

254
Jenkinsでdockerコンテナを利用したビルドでハマった問題
  • 様々なビルド環境を使い分けることを視野に入れると、Jenkinsのノード上に直接ビルド用の環境を作るよりもdockerコンテナ内でビルドしたい
  • しかしビルドした成果物への後処理(例:docker build)までコンテナでやろうとすると、コンテナの肥大化が気になる、またpublicに使われているコンテナをそのまま使えず、カスタマイズが大きく必要になる事もある

上記のような理由でJenkins上でdockerをスレーブノード上で動かしてビルドし、その成果物は同一ノード上だがコンテナ外でdocker buildなどの後処理を行おうとしたところ、とある問題でかなりハマったので備忘録がてら書いておく。

下記は現状では正しいと言えそうなpipeline定義の抜粋。

pipeline {
    agent none
    stages {
        stage('insideDocker') {
           docker {
             image REGISTRY_URL/IMAGE
             label NODE_NAME
             registryUrl REGISTRY_URL
             registryCredentialsId CREDENTIAL_ID
           }
           steps {  }
        }
        stage('outsideDocker') {
           agent {  label NODE_NAME }
           steps {  }
        }
    }
}

pipelineの冒頭でagent noneを指定し、stage単位で同じスレーブノードを使うように指定している。(もう少し改善できるとは思う。)

これをもしも次のようにやってしまうと、意図したとおりの挙動にならない。正しい方との差分は、dockerを使わないagentの指定を冒頭で行っているかoutsideDockerで行っているか。

pipeline {
    agent {  label NODE_NAME }
    stages {
        stage('insideDocker') {
           docker {
             image REGISTRY_URL/IMAGE
             label NODE_NAME
             registryUrl REGISTRY_URL
             registryCredentialsId CREDENTIAL_ID
           }
           steps {  }
        }
        stage('outsideDocker') {
           steps {  }
        }
    }
}

このような指定を行ってしまうと、JenkinsはinsideDockerステージとoutsideDockerステージでそれぞれ異なるワークスペースを割り当ててしまうようだ。この時、どうも最初にジョブが立ち上がった場所=workspace1、insideDocker=workspace2、outsideDocker=workspace1という形でワークスペースが使われる模様。

初回のビルドであればあるはずの成果物がないためにミスに気が付きやすいが、何らかの理由でpipeline定義をデグレードさせてしまった場合など、古い成果物を後段のステージで参照し続けるという、場合によってはかなり気が付きにくい問題を引き起こしてしまう。

上位でagent未指定の場合は同じagentを使い、同一のノードで新たなagentが指定されたらワークスペースを新たに作るという挙動は理解できるものなので、これは気を付けるしかないように思える。