JenkinsジョブをDockerfileから実行する際のデフォルトオプション



Page content

Jenkins PipelineジョブでDockerfileベースのイメージを使っていたら軽く躓いた話。




JenkinsジョブでDockerイメージをagentを指定

Jenkins Pipelineジョブでは、実行agentとしてDocker imageを指定できる。

agent {
    docker {
        image 'maven:3-alpine'
        args  '-v /tmp:/tmp'
    }
}

pullしたイメージを使えるだけでなく、自前のDockerfileからビルドしたイメージを使うこともできる。

agent {
    dockerfile {
        filename 'Dockerfile'
        additionalBuildArgs  '--build-arg version=1.0.2'
        args '-v /tmp:/tmp'
    }
}

Docker buildのデフォルト実行オプション

上記のように自前のDockerfileを使う場合、docker run時に以下のオプションがついた状態で実行される。

  • -d : デタッチド(バックグラウンド)
  • -t : 標準出力をつなぐ
  • -u JenkinsのUID:JenkinsのGID : Jenkins(のID)ユーザで実行
  • -w path/to/workspace : workspaceで実行
  • -v ***:*** : workspaceの内容をマウント
  • --entrypoint cat : entrypoint上書きしcat

ENTRYPOINTの話は以下の記事に少し書きました。

このデフォルトオプションには思惑があるだろうし、ジョブはworkspaceで実行する前提なんだろうけど、自分は少し困ることがあった。


ジョブによらずDockerのキャッシュを使いたい

以前、GitHubに成果物をpushしたら、CIでモジュールをS3に上げておき、JenkinsのDockerfileにそれを入れて展開する、といったようなことをしていた。

その際、いくつかのジョブで同様の処理を行っていた。


[参考記事]PlantUMLでAWSアイコンを使ったシステム構成図を作る


モジュールに差分が無ければキャッシュを使うことでジョブを高速化する狙いだったけど、ジョブごとに各々のworkspaceを実行ディレクトリにされてしまうと、ジョブが違えばキャッシュが効かなくなってしまう。


解決策

自分は結局、モジュールをルートディレクトリに展開して、

stage ('stage') {
  agent {
    dockerfile {
        filename 'Dockerfile'
        additionalBuildArgs  '...'
        args '...'
    }
  }
  steps {
      cd /
      ...
  }
}

cdするだけでした。すっきりする解決策ではないけど、これだけで問題なく動いたので。。


もう少しちゃんとした解決策

今後、デフォルトのオプションを上書きしないと無理〜な場面も出てくるかもしれないので、そちらの方法も確認。

stage ('stage') {
  steps {
    sh 'docker build -t my/image .'
    script {
      docker.image("my/image").withRun('-v $HOME/.m2:/root/.m2") {
        sh 'ls'
      }
    }
  }
}

確かに、自分でbuildしてrunすればいいですね。

参考サイトは以下。